2015-06-22 29 views
2

我想創建一個data.table對象,通過從其他data.tables中取出併合並它們。這裏有一個簡單的例子:如何逐行更新R data.table的所有列?

a <- data.frame(x=1:30) 
b <- data.frame(x=10:39) 
c <- data.frame(x=20:49) 

d <- data.frame(x=50:79) 
e <- data.frame(x=60:89) 
f <- data.frame(x=70:99) 

DT <- data.table(matrix(ncol = 3, nrow = 30)) 
for (i in seq.int(from = 1, to = 30, by = 3)) { 
    set(DT,i,.SD,cbind(a[i,],b[i,],c[i,])) 
    set(DT,(i+1),.SD,cbind(d[i,],e[i,],f[i,])) 
    set(DT,(i+2),.SD,"") 
} 

但是這是行不通的。我哪裏做錯了?任何人都可以推薦一個更好的方法來實現這種效果?我總覺得有點不安循環像這樣R.

所需的輸出應該是這樣的:(顯示第幾行)

 x x x 
1: 1 10 20 
2: 50 60 70 
3: 
4: 2 11 21 
5: 51 61 71 
6: 
7: 3 12 22 
8: 52 62 72 
9:   
10: 4 13 23 
+1

你能包括你想要你的輸出看起來像什麼嗎?你上面給出的代碼不適合我。 –

+1

'1:30'和'10:40'對於初學者來說長度不一樣。 – thelatemail

+0

您應該在示例輸出中包含更多行。 –

回答

3

大廈@ TimBiegeleisen的答案,這是由於某種原因被刪除:

library(data.table) 
pt1 <- data.table(a,b,c) 
pt2 <- data.table(d,e,f) 
out <- rbind(pt1,pt2) 
out[c(rbind(matrix(seq(1,nrow(out)),byrow=TRUE,nrow=2),NA))] 

out行索引上面是這樣的:1 31 NA 2 32 NA 3 33 NA,所以它抓住每個數據集的第一行,並把它們放在一起。 NA索引結果全部爲NA s。

#  x x x 
# 1: 1 10 20 
# 2: 50 60 70 
# 3: NA NA NA 
# 4: 2 11 21 
# 5: 51 61 71 
# 6: NA NA NA 
# 7: 3 12 22 
# 8: 52 62 72 
# 9: NA NA NA 
#10: 4 13 23 
#... 
+0

所有奇妙的答案,但這一個似乎是最直接的,並完成工作! – eyio

3

首先你有衝突的類,因爲你試圖將數字和字符分配給相同的列。所以我將分配NA而不是""

這就是說,這裏是一個使用data.table有一些修改您的解決方案,因此它的工作原理:

DT <- data.table(matrix(0, ncol = 3, nrow = 30)) 
j = 1 
for (i in seq.int(from = 1, to = 30, by = 3)) { 
    DT[i,names(DT):=list(a[j,],b[j,],c[j,]), with = FALSE] 
    DT[i+1,names(DT):=list(d[j,],e[j,],f[j,]), with = FALSE] 
    DT[(i+2),names(DT):=NA, with = FALSE] 
    j = j + 1 
} 
DT 
    V1 V2 V3 
1: 1 10 20 
2: 50 60 70 
3: NA NA NA 
4: 2 11 21 
5: 51 61 71 
6: NA NA NA 
7: 3 12 22 
8: 52 62 72 
9: NA NA NA 
10: 4 13 23 
11: 53 63 73 
12: NA NA NA 
13: 5 14 24 
14: 54 64 74 
15: NA NA NA 
16: 6 15 25 
17: 55 65 75 
18: NA NA NA 
19: 7 16 26 
20: 56 66 76 
21: NA NA NA 
22: 8 17 27 
23: 57 67 77 
24: NA NA NA 
25: 9 18 28 
26: 58 68 78 
27: NA NA NA 
28: 10 19 29 
29: 59 69 79 
30: NA NA NA 
    V1 V2 V3 

使用apply(而不是使用data.table)另一種解決方案:

df <- apply(cbind(a,b,c,d,e,f), 1, function(x) rbind(data.frame(x=x[1], y=x[2], z=x[3]), 
               data.frame(x=x[4], y=x[5], z=x[6]), 
               data.frame(x=NA, y = NA, z = NA))) 
df <- do.call("rbind", df) 
+0

感謝您的答案卡洛斯!應用解決方案非常有趣。有什麼辦法讓它動態嗎?在data.table中,例如,如果我不知道事先有多少列(a,b,c),是否有一種方法來推廣此代碼? – eyio

2

可能是有更多的這樣做的有效方法:

rows2<-seq.int(1,30,3) 
rows3<-1:10 
n2<-length(rows3) 
h1<-list(a[rows3,],b[rows3,],c[rows3,]) 
h2<-list(d[rows3,],e[rows3,],f[rows3,]) 
h3<-list(rep("",n2),rep("",n2),rep("",n2)) 

DT <- data.table(matrix(0,ncol = 3, nrow = 30)) 
for (j in 1:3) { 
    set(DT,i=rows2,j=j,value=h1[[j]]) 
    set(DT,i=rows2+1,j=j,value=h2[[j]]) 
    set(DT,i=rows2+2,j=j,value=h3[[j]]) 
} 
    DT 
    V1 V2 V3 
1: 1 10 20 
2: 50 60 70 
3: NA NA NA 
4: 2 11 21 
5: 51 61 71 
6: NA NA NA 
7: 3 12 22 
8: 52 62 72 
9: NA NA NA 
10: 4 13 23 
11: 53 63 73 
12: NA NA NA 
13: 5 14 24 
14: 54 64 74 
15: NA NA NA 
16: 6 15 25 
17: 55 65 75 
18: NA NA NA 
19: 7 16 26 
20: 56 66 76 
21: NA NA NA 
22: 8 17 27 
23: 57 67 77 
24: NA NA NA 
25: 9 18 28 
26: 58 68 78 
27: NA NA NA 
28: 10 19 29 
29: 59 69 79 
30: NA NA NA 
    V1 V2 V3 
+0

感謝您的解決方案!這裏的問題是我想要的一些行由於子集的完成而被跳過。在問題中看到期望的結果,我最近更新了它希望清楚。謝謝! – eyio

+0

你的a [4] == 4,b [4] = 13和c [4] = 23'。你是怎麼得到這些「2,11,21」的? – user227710

+0

在這個例子中,輸出應該分成3行,第一行是a,b,c的第一行;第二行是d,e,f和第三行的第一行是平淡的;然後,在第二組(從第四行開始)中,第四行應該是a,b,c的第二行;第五排應該是d,e,f的第二排,第6排應該是空白的 – eyio