2013-02-08 24 views
5

Tôi đã tạo ra một chức năng đó được gọi là để đọc trong và sau đó trả về một data.table:Thủ thuật để tránh sao chép phân bổ bộ nhớ khi trả về dữ liệu.table hoặc data.frame trong R?

read.in.data <- function(filename) 
{ 
    library(data.table) 
    data.holder<-read.table(filename, skip=1) 
    return(data.table(data.holder)) 
} 

tôi đã nhận thấy từ quan sát RAM của tôi như là các quá trình chức năng R dường như để xử lý này trong 2 bước (hoặc ít nhất đây là dự đoán tốt nhất của tôi cho những gì đang xảy ra). Ví dụ, khi tôi tải một tập tin 1.5 GB (15 cột với tổng số 136 ký tự mỗi hàng), R có vẻ là 1) đọc trong dữ liệu và sử dụng 1,5 GB RAM, và sau đó 2) sử dụng 1,5 GB RAM khác cho sự trở lại.

Có một số thủ thuật để tạo một hàm để tạo một data.table (hoặc data.frame cho vấn đề đó) và trả về data.table mà không yêu cầu sao chép trong bộ nhớ? Hoặc tôi phải làm tất cả các xử lý cho data.table trong hàm mà bảng được tạo ra?

Quan sát: Nếu tôi chạy mã này hai lần liên tiếp, bộ nhớ sẽ không bị xóa; vì tôi chỉ có 8 GB RAM, chức năng không thành công. Nếu tôi bỏ qua bước lưu trữ "read.table" trong một biến (như được hiển thị bên dưới), tôi không nhận được bất kỳ lợi ích nào. Tôi sẽ không muốn làm điều này theo bất kỳ cách nào, vì tôi muốn có khả năng dọn sạch dữ liệu trước khi trả lại dữ liệu. Khắc phục sự cố của tôi cũng sẽ cho phép tôi xử lý các tệp lớn hơn mà không cần hết bộ nhớ.

short.read.trk <- function(fntrk) 
{ 
    library(data.table) 
    return(data.table(read.table(fntrk, skip=1))) 
} 
+4

Tôi cảm thấy đau đớn của bạn. Hãy thử fread() trong v1.8.7. Nó tạo ra một data.table trực tiếp để (copy) data.table() wrapper có thể tránh được, cộng với nó hiệu quả hơn read.table anyway (ngay cả với tất cả các thủ thuật đã biết). –

+0

Cảm ơn bạn, tôi sẽ thử fread() ngay sau khi 1.8.7 có một bản dựng trên r-forge (hiện đang liệt kê là "không thể xây dựng"). – Docuemada

+0

Rất tiếc - cảm ơn vì đã cho tôi biết - Tôi sẽ xem xét ... –

Trả lời

2

Nếu tiết kiệm bộ nhớ được hầu hết những gì bạn đang sau, bạn có thể chuyển đổi nó một cột tại một thời điểm:

library(data.table) 
read.in.data <- function(filename) 
{ 
    data.holder <- read.table(filename, skip=1) 
    dt <- data.table(data.holder[[1]]) 
    names(dt) <- names(data.holder)[1] 
    data.holder[[1]] <- NULL 

    for(n in names(data.holder)) { 
    dt[, `:=`(n, data.holder[[n]]) ] 
    data.holder[[n]] <- NULL 
    } 
    return(dt) 
} 

(chưa được kiểm tra)

Nó sẽ không có bất kỳ nhanh hơn, thực tế nó có thể chậm hơn. Nhưng nó sẽ ít lãng phí bộ nhớ hơn.

+0

Cảm ơn bạn, đây là một cách tiếp cận thú vị. Tôi sẽ thực hiện nó khi tôi có quyền truy cập vào tập dữ liệu vào thứ hai và chỉnh sửa nhận xét này với kết quả. – Docuemada

+1

+1 Cách tiếp cận thú vị. Điều đó có thể thực sự rất nhanh. Các cách tiếp cận khác để thử nghiệm là 'as.data.table()' thay vì 'data.table()' và (chỉ dành cho các chuyên gia): 'setattr (dữ liệu," lớp ", c (" data.frame "," dữ liệu. bảng "))'. –

+0

+1 Tôi thích cách tiếp cận sử dụng "NULL" để giữ bộ nhớ ở mức thấp. Tôi đã thử nó khi gắn các bảng lại với nhau. Ví dụ, tôi đã thử nó bằng cách sử dụng một cái gì đó như dt <-do.call ("rbind", danh sách (dt, dt.holder)) theo sau là dt.holder <-NULL. Tuy nhiên, cách tiếp cận trên không thay đổi RAM tổng thể được sử dụng. Khi so sánh kịch bản gốc của tôi với kịch bản được đề xuất, việc sử dụng RAM là như nhau. – Docuemada

Các vấn đề liên quan