我有两个数据表,DT1和DT2:
set.seed(1)
DT1<-data.table(id1=rep(1:3,2),id2=sample(letters,6), v1=rnorm(6), key="id2")
DT1
## id1 id2 v1
## 1: 2 e 0.7383247
## 2: 1 g 1.5952808
## 3: 2 j 0.3295078
## 4: 3 n -0.8204684
## 5: 3 s 0.5757814
## 6: 1 u 0.4874291
DT2<-data.table(id2=c("n","u"), v1=0, key="id2")
DT2
## id2 v1
## 1: n 0
## 2: u 0
我想基于与DT2的连接更新DT1,但仅针对DT1的子集。例如,对于DT1[id1==3]
,我希望第4行中的v1值可以更新,如下所示:
DT1
## id1 id2 v1
## 1: 2 e 0.7383247
## 2: 1 g 1.5952808
## 3: 2 j 0.3295078
## 4: 3 n 0
## 5: 3 s 0.5757814
## 6: 1 u 0.4874291
我知道如何更新表(使用:=
赋值运算符),如何连接表(DT1[DT2]
)以及如何对表(DT1[id1==3]
)进行子集。但是我不确定如何一次完成这三个。
修改 请注意,原始示例仅尝试更新一列,但我的实际数据需要更新许多列。考虑DT1b和DT2b中的其他方案:
set.seed(2)
DT1b<-DT1[,v2:=rnorm(6)] # Copy DT1 and add a new column
setkey(DT1b,id2)
DT1b
## id1 id2 v1 v2
## 1: 2 e 0.7383247 -0.89691455
## 2: 1 g 1.5952808 0.18484918
## 3: 2 j 0.3295078 1.58784533
## 4: 3 n -0.8204684 -1.13037567
## 5: 3 s 0.5757814 -0.08025176
## 6: 1 u 0.4874291 0.13242028
DT2b<-rbindlist(list(DT2,data.table(id2="e",v1=0))) # Copy DT2 and add a new row
DT2b[,v2:=-1] # Add a new column to DT2b
setkey(DT2b,id2)
DT2b
## id2 v1 v2
## 1: e 0 -1
## 2: n 0 -1
## 3: u 0 -1
根据@nmel和@BlueMagister的有用答案,我想出了更新方案的解决方案:
DT1b[DT2b[DT1b[id1 %in% c(1,2)],nomatch=0],c("v1","v2"):=list(i.v1,i.v2)]
DT1b
## id1 id2 v1 v2
## 1: 2 e 0.0000000 -1.00000000
## 2: 1 g 1.5952808 0.18484918
## 3: 2 j 0.3295078 1.58784533
## 4: 3 n -0.8204684 -1.13037567
## 5: 3 s 0.5757814 -0.08025176
## 6: 1 u 0.0000000 -1.00000000
答案 0 :(得分:15)
我能想到的最简单方法是按id1
键。
例如
setkey(DT1, id2,id1)
DT2[, id1 := 3]
setkey(DT2, id2, id1)
# use i.v1 to reference v1 from the i component
DT1[DT2, v1 := i.v1 ]
DT1
id1 id2 v1
1: 2 e 0.7383247
2: 1 g 1.5952808
3: 2 j 0.3295078
4: 3 n 0.0000000
5: 3 s 0.5757814
6: 1 u 0.4874291
答案 1 :(得分:9)
答案 2 :(得分:0)
这些天我一直在想这个问题。以下是我的解决方法。
DT1[DT2, names(DT2):= DT2, on= 'id']
或者,如果您不希望在DT2私有的变量中向DT1添加新变量:
common.var <- intersect(names(DT1), names(DT2))
DT1[DT2, c(common.var) := DT2[, common.var, with= FALSE] ,on= 'id']