Перетворити кадр даних на data.table без копії


81

У мене є великий фрейм даних (порядку декількох ГБ), який я хотів би перетворити на 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

Відповіді:


93

Це доступно з версії 1.9.0 + . З НОВИН :

o Після цієї публікації SOsetDT тепер реалізована функція , яка приймає 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*

Дивіться історію для старих (на сьогодні застарілих) відповідей.


@Arun: Дякую за детальну відповідь. Я насправді запитував, як перетворити фрейм даних у data.table, але недбало створював приклад іграшки, я оновлю своє запитання, щоб зробити його фреймом даних. Чи спрацює тоді та сама ідея для кадру даних, наприклад, позбавлення від перших двох setattr, оскільки фрейм даних уже їх має, а решта збереже?
ytsaig

@YT, якщо ви маєте на увазі отримання "data.frame" до "data.table", то, звичайно, те, що ви кажете, є правильним. Якщо ви маєте на увазі список data.frames, то вам доведеться прив'язати їх (стовпці або рядки) перед тим, як встановити клас і розподілити.
Арун

@Arun, я мав на увазі перший, єдиний кадр даних для data.table, я відредагував питання, щоб, сподіваюся, краще його відобразити. Ще раз дякую за розумне рішення, я можу прийняти відповідь такою, якою вона є, або почекати, якщо ви хочете відредагувати її відповідно до переглянутих питань.
ytsaig

2
Можливо, цей допис від Метью допоможе пролити більше світла truelength.
Арун

3
@eddi До R2.14.0 truelengthчлен заголовка вектора R не був ініціалізований R. У C, якщо ви не ініціалізуєте змінну, вона має невизначений вміст (що б раніше не було в цій частині оперативної пам'яті). data.table()та подібні творці ініціалізують truelengthдо 0, перш ніж вимагати alloc.colсумісності з попередньою версією 2.14.0. alloc.colрозглядається truelengthяк вхід (0 прийнято означати truelength == length). Одного разу я думав, що data.table через це повинен залежати від R> = 2.14.0, але вдалося зберегти його R> = 2.12.0. Я тестую з R2.12.0 перед кожним випуском у CRAN.
Matt Dowle
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.