2013-02-20 22 views
9

Tôi có một data.table mà tôi muốn chia thành hai. Tôi làm điều này như sau:chia dữ liệu.table

dt <- data.table(a=c(1,2,3,3),b=c(1,1,2,2)) 
sdt <- split(dt,dt$b==2) 

nhưng nếu tôi muốn một cái gì đó như thế này như một bước tiếp theo

sdt[[1]][,c:=.N,by=a] 

tôi nhận được thông báo sau. nhắn

Cảnh báo: Trong [.data.table (sdt [[1]],, := (c, Đô), bởi = a): .internal.selfref không hợp lệ phát hiện và cố định bằng cách lấy một bản sao của toàn bảng, do đó: = có thể thêm cột mới này bằng cách tham chiếu. Tại một điểm trước đó, dữ liệu này có thể được sao chép bằng R. Tránh khóa < -, tên < - và attr < - trong đó R hiện tại (và kỳ quặc) có thể sao chép toàn bộ dữ liệu . Thay vào đó, hãy sử dụng cú pháp set * để tránh sao chép: setkey(), tên set() và setattr(). Ngoài ra, danh sách (DT1, DT2) sẽ sao chép toàn bộ DT1 và DT2 (các bản sao của danh sách R() có tên là đối tượng), sử dụng hàm reflist() thay thế nếu cần (để được triển khai). Nếu thông báo này không hữu ích, vui lòng báo cáo về dữ liệu có thể trợ giúp để nguyên nhân gốc rễ có thể được khắc phục.

Chỉ cần tự hỏi liệu có cách nào tốt hơn là tách bảng sao cho hiệu quả hơn (và không nhận được thông báo này)?

+3

Tại sao bạn muốn chia data.table ở nơi đầu tiên? Tách chúng tôi tạo danh sách, vì vậy cảnh báo đề cập đến lý do tại sao bản sao đã diễn ra – mnel

+0

Tôi đang tạo hai bộ cho thử nghiệm của mình, dựa trên phân chia thời gian. – jamborta

+0

Tôi tò mò về ý nghĩa của '.N' trong trường hợp này? –

Trả lời

10

này hoạt động trong v1.8.7 (và có thể làm việc trong v1.8.6 quá):

> sdt = lapply(split(1:nrow(dt), dt$b==2), function(x)dt[x]) 
> sdt 
$`FALSE` 
    a b 
1: 1 1 
2: 2 1 

$`TRUE` 
    a b 
1: 3 2 
2: 3 2 

> sdt[[1]][,c:=.N,by=a]  # now no warning 
> sdt 
$`FALSE` 
    a b c 
1: 1 1 1 
2: 2 1 1 

$`TRUE` 
    a b 
1: 3 2 
2: 3 2 

Nhưng, như @mnel nói, đó là không hiệu quả. Hãy tránh chia tách nếu có thể.

+1

Tôi không hoàn toàn hiểu tại sao nó nói 'không hợp lệ .internal.selfref' như khi tôi làm 'thuộc tính (sdt [[1]]) $. Internal.selfref', giá trị có vẻ giống như một cho' dt' (và tương tự trên 'dt2 <- copy (dt)') .. Bất kỳ suy nghĩ nào? – Arun

+3

@Chạy Chính xác, đó là lý do tại sao nó không hợp lệ. Đó là nghĩa vụ phải trỏ đến chính nó khi hợp lệ. Nếu bạn nhìn vào '.Internal (checking (sdt [[1]]))' bạn sẽ thấy địa chỉ con trỏ của nó là khác nhau (một bản sao đã được chụp). Đó là những gì '.internal.selfref' được thiết kế để phát hiện. Vấn đề với bản sao không quá nhiều bản sao cho mỗi bản sao, nhưng khi R sao chép nó không duy trì vectơ phân bổ trên các con trỏ cột. Do đó cảnh báo khi ': =' cố gắng thêm một cột mới (nó phải phân bổ lại lần nữa) trong trường hợp bạn có hai ràng buộc với cùng một đối tượng. Tất cả chính xác và dự định. –

+2

@Arun Vì vậy, cảnh báo đang cố gắng để nói: không 'cơ sở :: chia' tìm một số cách khác, chẳng hạn như câu trả lời của tôi, để làm việc phân chia. –

4

Tôi đang tìm một số cách để chia nhỏ dữ liệu. Có thể, tôi đã xem qua câu hỏi cũ này.

Thỉnh thoảng chia nhỏ là những gì bạn muốn làm, và cách tiếp cận dữ liệu có thể không thuận tiện.

Trên thực tế bạn có thể dễ dàng làm chia của bạn bằng tay với data.table chỉ hướng dẫn và nó hoạt động rất hiệu quả:

SplitDataTable <- function(dt,attr) { 
    boundaries=c(0,which(head(dt[[attr]],-1)!=tail(dt[[attr]],-1)),nrow(dt)) 
    return(
    mapply(
     function(start,end) {dt[start:end,]}, 
     head(boundaries,-1)+1, 
     tail(boundaries,-1), 
     SIMPLIFY=F)) 
} 
Các vấn đề liên quan