2012-05-24 35 views
8

Tôi đang tìm giải pháp thay thế tốt nhất cho bài tập chưa được thực hiện (với kiến ​​thức của tôi) bằng cách tham chiếu trong một dữ liệu. Có thể theo nhóm. Sử dụng ví dụ data.table,data.table thay thế hiệu quả để gán theo nhóm như DT [, x: = f (y), bởi = z]?

DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9) 
    x y v 
[1,] a 1 1 
[2,] a 3 2 
[3,] a 6 3 
[4,] b 1 4 
[5,] b 3 5 
[6,] b 6 6 
[7,] c 1 7 
[8,] c 3 8 
[9,] c 6 9 

Tôi muốn thêm một cột z mới, chứa f (y, v) được phân nhóm theo các giá trị của x (cho phép chụp f (y, v) = trung bình (y) + v). Lưu ý rằng tôi không muốn in hoặc lưu trữ kết quả tính toán này như trong

DT[,mean(y)+v,by=x] 
     x  V1 
[1,] a 4.333333 
[2,] a 5.333333 
[3,] a 6.333333 
[4,] b 7.333333 
[5,] b 8.333333 
[6,] b 9.333333 
[7,] c 10.333333 
[8,] c 11.333333 
[9,] c 12.333333 

mà là tôi muốn thêm vào kết quả để DT:

 x y v  V1 
[1,] a 1 1 4.333333 
[2,] a 3 2 5.333333 
[3,] a 6 3 6.333333 
[4,] b 1 4 7.333333 
[5,] b 3 5 8.333333 
[6,] b 6 6 9.333333 
[7,] c 1 7 10.333333 
[8,] c 3 8 11.333333 
[9,] c 6 9 12.333333 

data.table của tôi có 262 MB, sao cho

DT <- DT[,transform(.SD,mean(y)+v),by=x] 

không phải là một tùy chọn vì tôi không thể khớp DT hai lần trong bộ nhớ (điều này được ngụ ý bởi thao tác sao chép). Thực tế là tôi chưa bao giờ thấy kết thúc hoạt động đó.

Tôi có những lựa chọn nào (cho đến khi data.table đi kèm với DT [, z: = mean (y) + v, by = x])?

Tôi chỉ đọc về DT [newDT]. Có gì sai ở đây?

newDT <- DT[,mean(y)+v,by=x] 
     x  V1 
[1,] a 4.333333 
[2,] a 5.333333 
[3,] a 6.333333 
[4,] b 7.333333 
[5,] b 8.333333 
[6,] b 9.333333 
[7,] c 10.333333 
[8,] c 11.333333 
[9,] c 12.333333 

(đó là bộ nhớ doable khôn ngoan.) Sau đó:

> DT[newDT] 
setkey(DT,x) 
setkey(newDT,x) 
x y v  V1 
a 1 1 4.333333 
a 3 2 4.333333 
a 6 3 4.333333 
a 1 1 5.333333 
a 3 2 5.333333 
a 6 3 5.333333 
a 1 1 6.333333 
a 3 2 6.333333 
a 6 3 6.333333 
b 1 4 7.333333 
b 3 5 7.333333 
b 6 6 7.333333 
b 1 4 8.333333 
b 3 5 8.333333 
b 6 6 8.333333 
b 1 4 9.333333 
b 3 5 9.333333 
b 6 6 9.333333 
c 1 7 10.333333 
c 3 8 10.333333 
c 6 9 10.333333 
c 1 7 11.333333 
c 3 8 11.333333 
c 6 9 11.333333 
c 1 7 12.333333 
c 3 8 12.333333 
c 6 9 12.333333 

nhưng đó không phải là những gì tôi muốn. Sai lầm ở đây là gì?

+0

+1 Great câu hỏi! –

Trả lời

4
DT[, xm := ave(y, x, FUN=mean) + v] 
+0

1 giải pháp rất hay, tôi chỉ viết một câu dài vì tôi nghĩ bạn không làm việc. Có một cái nhìn thứ hai về 'ave', tôi nghĩ bạn có nghĩa là 'DT [, xm: = ave (y, x, FUN = trung bình) + v]'. Sau đó, nó hoạt động như một say mê và có thể là hiệu quả nhất. –

+1

+1 Vì ', by' nhanh hơn' ave', điều này sẽ hiệu quả hơn (mặc dù xấu xí) cho đến khi "': = 'theo nhóm" kết thúc: 'DT [, xm: = DT [, mean (y) + v, by = x] [[2]]] ' –

+0

cảm ơn một anh chàng rất nhiều. Tôi thậm chí không biết 'ave' tồn tại. mong chờ nhóm ': =' theo nhóm! –

3

tôi sẽ làm như sau:

DT[, list(fvy = mean(y)), by="x"][DT][, fvy := fvy + v] 

Vì vậy, về cơ bản, tôi tách nó ra thành hai phần: Thứ nhất, tôi tính toán giá trị trung bình của y và thêm rằng để DT, sau đó tôi thêm v để giá trị trung bình của y. Trí nhớ-khôn ngoan Tôi không chắc chắn nếu điều này thực sự giúp, nhưng có một cơ hội tốt tác giả sẽ có một cái nhìn và cho chúng tôi biết ;-)

Về câu hỏi của bạn tại sao nó không hoạt động: Về cơ bản, bạn kết thúc với hai data.tables mà bạn muốn hợp nhất: DTnewDT. Cả hai data.tables có mỗi khóa ba lần. Vì vậy, rõ ràng, khi bạn hợp nhất chúng, mọi kết hợp đều có trong kết quả và đó là lý do tại sao bạn nhận được dữ liệu.table với 9 a, b và c.

Vì vậy, để làm điều đó theo cách của bạn là khá giống với khai thác bạn cần một chìa khóa thứ hai:

newDT <- DT[,list(fvy=mean(y)+v, v),by=x] 
setkey(newDT, x, v) 
setkey(DT, x, v) 
DT[newDT] 
     x v y  fvy 
[1,] a 1 1 4.333333 
[2,] a 2 3 5.333333 
[3,] a 3 6 6.333333 
[4,] b 4 1 7.333333 
[5,] b 5 3 8.333333 
[6,] b 6 6 9.333333 
[7,] c 7 1 10.333333 
[8,] c 8 3 11.333333 
[9,] c 9 6 12.333333 
+1

+1 cho nỗ lực. Chúng tôi thực sự chỉ cần ': =' theo nhóm, đúng không. Gần đó. Btw, hợp chất ': =' có ích đôi khi: 'DT [, newx: = colA + 2] [, newy: = newx * 2] [, newz: = colA + newx + newy] ...' –

+2

Nhưng tôi sẽ không làm nhiều ': =' bởi 'bởi', chỉ trong trường hợp ai đó đang hy vọng điều đó. Nó sẽ chỉ là một ': =' bởi 'bởi' cho phiên bản tiếp theo. Các phiên bản tương lai có thể là 'DT [, {newx: = colB + 2; newy: = newx + colC}, bởi = colA]' –

+0

nhờ christoph_J. điều quan trọng đó có ý nghĩa tổng thể. –

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