Chuyển đổi khung dữ liệu thành data.table mà không cần sao chép


81

Tôi có một khung dữ liệu lớn (theo thứ tự vài GB) mà tôi muốn chuyển đổi thành a data.table. Việc sử dụng as.data.tablesẽ tạo ra một bản sao của khung dữ liệu, có nghĩa là tôi cần bộ nhớ khả dụng có kích thước ít nhất gấp đôi dữ liệu. Có cách nào để thực hiện chuyển đổi mà không cần bản sao không?

Đây là một ví dụ đơn giản để chứng minh:

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()

Với đầu ra:

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

Câu trả lời:


92

Điều này có sẵn từ v1.9.0 + . Từ TIN TỨC :

o Sau bài đăng SO này , một hàm setDThiện được triển khai lấy một list(có tên và / hoặc không tên), data.frame(hoặc data.table) làm đầu vào và trả về cùng một đối tượng dưới dạng data.table tham chiếu (không có bất kỳ bản sao nào). Xem ?setDTví dụ để biết thêm.

Điều này phù hợp với data.tablequy ước đặt tên - tất cả các set*hàm sửa đổi bằng cách tham chiếu. :=là cái khác duy nhất cũng sửa đổi theo tham chiếu.

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

Xem lịch sử để biết các câu trả lời cũ hơn (hiện đã lỗi thời).


@Arun: Cảm ơn vì câu trả lời chi tiết. Tôi thực sự đang hỏi làm thế nào để chuyển đổi một khung dữ liệu thành data.table, nhưng rất cẩu thả trong việc tạo ví dụ đồ chơi, tôi sẽ cập nhật câu hỏi của mình để biến nó thành khung dữ liệu. Liệu ý tưởng tương tự sau đó có hoạt động đối với một khung dữ liệu, ví dụ: loại bỏ hai setattr đầu tiên vì một khung dữ liệu đã có những thứ này và giữ phần còn lại?
ytsaig

@YT, nếu ý bạn là lấy "data.frame" thành "data.table", thì tất nhiên điều bạn nói là đúng. Nếu ý bạn là danh sách data.frame, thì bạn sẽ phải liên kết chúng (theo cột hoặc theo hàng) trước đó để đặt lớp và phân bổ.
Arun

@Arun, ý tôi là trước đây, một khung dữ liệu duy nhất cho data.table, tôi đã chỉnh sửa câu hỏi để hy vọng phản ánh nó tốt hơn. Cảm ơn một lần nữa vì một giải pháp thông minh, tôi có thể chấp nhận câu trả lời như hiện tại hoặc đợi nếu bạn muốn chỉnh sửa nó để phù hợp với câu hỏi đã sửa đổi.
ytsaig

2
Có thể bài đăng này của Matthew sẽ giúp làm sáng tỏ hơn truelength.
Arun

3
@eddi Trước R2.14.0, phần truelengthtử của tiêu đề vectơ của R không được khởi tạo bởi R. Trong C nếu bạn không khởi tạo một biến thì nó có nội dung không xác định (bất kỳ điều gì xảy ra trong đoạn RAM đó trước đó). data.table()và những người sáng tạo tương tự khởi tạo truelengththành 0 trước khi yêu alloc.colcầu khả năng tương thích với trước R 2.14.0. alloc.colđược xem truelengthnhư một đầu vào (0 được coi là chiều dài truelength ==). Tại một thời điểm, tôi nghĩ data.table sẽ cần phụ thuộc vào R> = 2.14.0 vì điều này, nhưng đã quản lý để giữ nó R> = 2.12.0. Tôi kiểm tra với R2.12.0 trước mỗi lần phát hành cho CRAN.
Matt Dowle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.