19

DT1とDT2の2つのデータテーブルがあります。

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]。ただし、3つすべてを一度に実行する方法がわかりません。

編集: 元の例では1つの列のみを更新しようとしていますが、実際のデータでは多くの列を更新する必要があることに注意してください。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
4

3 に答える 3

16

私が考えることができる最も簡単な方法は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
于 2013-02-06T03:41:16.013 に答える
10

これはmnelソリューションifelseに似ていますが、2番目のキーの代わりに使用します。

DT1[DT2, v1  := ifelse(id1==3, i.v1, v1),nomatch=0]
于 2013-02-06T04:26:32.037 に答える
1

私は最近この質問を考えています。以下は私の解決策です。

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']
于 2020-11-16T15:21:56.913 に答える