Подтвердить что ты не робот

Преобразование фрейма данных в таблицу данных без копии

У меня есть большой кадр данных (порядка нескольких ГБ), который я бы хотел преобразовать в data.table. Использование as.data.table создает копию фрейма данных, что означает, что мне нужна доступная память как минимум в два раза превышающая размер данных. Есть ли способ сделать преобразование без копии?

Вот простой пример для демонстрации:

library(data.table)
N <- 1e6
K <- 1e2
data <- as.data.frame(rep(data.frame(rnorm(N)), K))

gc(reset=TRUE)
tracemem(data)
data <- as.data.table(data)
gc()

С выходом:

library(data.table)
# data.table 1.8.10  For help type: help("data.table")
N <- 1e6
K <- 1e2
data <- as.data.frame(rep(data.frame(rnorm(N)), K))

gc(reset=TRUE)
# used  (Mb) gc trigger   (Mb)  max used  (Mb)
# Ncells    303759  16.3     597831   32.0    303759  16.3
# Vcells 100442572 766.4  402928632 3074.2 100442572 766.4
tracemem(data)
# [1] "<0x363fda0>"
data <- as.data.table(data)
# tracemem[0x363fda0 -> 0x31e4260]: copy as.data.table.data.frame as.data.table 
gc()
# used  (Mb) gc trigger   (Mb)  max used   (Mb)
# Ncells    304519  16.3     597831   32.0    306162   16.4
# Vcells 100444242 766.4  322342905 2459.3 200933219 1533.0
4b9b3361

Ответ 1

Это доступно из v1.9.0 +. Из NEWS:

o Следуйте за этим S.O. post, теперь реализована функция setDT, которая принимает list (именованный и/или неназванный), data.frame (или data.table) и возвращает тот же объект, что и data.table по ссылке (без какой-либо копии). Более подробно см. Примеры ?setDT.

Это соответствует соглашению об именах data.table - все функции set* изменяются по ссылке. := является единственным, который также модифицирует по ссылке.

require(data.table) # v1.9.0+
setDT(data) # converts data which is a data.frame to data.table *by reference*

См. историю для более старых (теперь устаревших) ответов.

Ответ 2

Это очень просто. В этом случае преобразование CSV файла, который R сохраняет в качестве фрейма данных.

housing_url <- "https://d396qusza40orc.cloudfront.net/getdata%2Fdata%2Fss06pid.csv"
download.file(housing_url, destfile = "./housing.csv", method = "curl")
require(data.table)
DTableFile <- as.data.table(read.csv("./data/housing.csv"))