2015-06-22 67 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