R 按五列匹配数据表以更改另一列中的值

R 按五列匹配数据表以更改另一列中的值,r,amazon-web-services,parallel-processing,data.table,R,Amazon Web Services,Parallel Processing,Data.table,我有Ubuntu 16.04,在终端上运行R。 我正在处理大数据表,一个有7500万行11列(dt1),另一个有700万行7列(dt2)。所有值都是数字。两个表都有“id”列。我需要找到第一个表中的所有行,这些行的五列值与第二个表中的五列值相同,并将第一个数据表中这些行的“id”值更改为第二个数据表中的值。在两个数据表中,比较的列具有相同的名称,可以说它们是V1、V2、V3、V4和V5。我已经将第二个数据表转换为数据帧格式,所以我可以使用它的“id”作为索引。我试了1000排,花了40分钟 fo

我有Ubuntu 16.04,在终端上运行R。 我正在处理大数据表,一个有7500万行11列(dt1),另一个有700万行7列(dt2)。所有值都是数字。两个表都有“id”列。我需要找到第一个表中的所有行,这些行的五列值与第二个表中的五列值相同,并将第一个数据表中这些行的“id”值更改为第二个数据表中的值。在两个数据表中,比较的列具有相同的名称,可以说它们是V1、V2、V3、V4和V5。我已经将第二个数据表转换为数据帧格式,所以我可以使用它的“id”作为索引。我试了1000排,花了40分钟

for (i in 1:1000) {
    dt1[(V1==dt2[i,V1] & V2==dt2[i,V2] &
         V3==dt2[i,V3] & V4==dt2[i,V4] &
         V5==dt2[i,V5]), id:=i]
}

我打算将其并行化,但由于内存限制,我只能使用2或3个内核。显然,这是不够的。在我的家庭电脑上有没有快速有效的方法?如果要在AWS上实现,有哪些技巧是有用的?特别是,我可以同时使用多少个核?

在R中,最好尽可能避免循环,因为它们通常比其他矢量化解决方案慢得多

此操作可以通过data.table联接完成。基本上,当你跑步的时候

dt1[dt2];
您正在两个data.Table之间执行右联接。
dt1
的预设键列确定要连接的列。如果
dt1
没有预设键,则操作失败。但您可以指定
on
参数来动态手动选择键列:

key <- paste0('V',1:5);
dt1[dt2,on=key];
下面是一个仅使用两个键列和几行数据的示例(为了简单起见)。我还生成了包含一些不匹配行的键,只是为了演示不匹配行的ID不会被操作触及

set.seed(1L);
dt1 <- data.table(id=1:12,expand.grid(V1=1:3,V2=1:4),blah1=rnorm(12L));
dt2 <- data.table(id=13:18,expand.grid(V1=1:2,V2=1:3),blah2=rnorm(6L));
dt1;
##     id V1 V2      blah1
##  1:  1  1  1 -0.6264538
##  2:  2  2  1  0.1836433
##  3:  3  3  1 -0.8356286
##  4:  4  1  2  1.5952808
##  5:  5  2  2  0.3295078
##  6:  6  3  2 -0.8204684
##  7:  7  1  3  0.4874291
##  8:  8  2  3  0.7383247
##  9:  9  3  3  0.5757814
## 10: 10  1  4 -0.3053884
## 11: 11  2  4  1.5117812
## 12: 12  3  4  0.3898432
dt2;
##    id V1 V2       blah2
## 1: 13  1  1 -0.62124058
## 2: 14  2  1 -2.21469989
## 3: 15  1  2  1.12493092
## 4: 16  2  2 -0.04493361
## 5: 17  1  3 -0.01619026
## 6: 18  2  3  0.94383621
key <- paste0('V',1:2);
dt1[dt2,on=key,id:=i.id];
dt1;
##     id V1 V2      blah1
##  1: 13  1  1 -0.6264538
##  2: 14  2  1  0.1836433
##  3:  3  3  1 -0.8356286
##  4: 15  1  2  1.5952808
##  5: 16  2  2  0.3295078
##  6:  6  3  2 -0.8204684
##  7: 17  1  3  0.4874291
##  8: 18  2  3  0.7383247
##  9:  9  3  3  0.5757814
## 10: 10  1  4 -0.3053884
## 11: 11  2  4  1.5117812
## 12: 12  3  4  0.3898432
set.seed(1L);

dt1非常感谢您快速详细的回复!如果有一些不匹配,我只关心第二个表中的所有匹配,我应该使用all.y=T,对吗?所有不匹配项都将标记为NA?Hi@Mathemilda。看来我们在数据表的功能上发现了一个漏洞。我找不到任何使用
dt1[dt2]
index-join语法来实现左连接的方法,这正是我们在这里需要的。
merge.data.table()
函数支持
all.y
参数,但不支持指定赋值的
j
参数,因此我们不能使用该参数。索引函数的
nomatch
参数仅支持从右连接(
nomatch=NA
,这是默认值)更改为内部连接(
nomatch=0
)。无法在同一索引联接分配中用NA替换不匹配项。一种解决方法是在运行索引联接分配操作之前,有效地使整个
id
列无效,然后仅从
dt2
设置匹配行。其余部分将保留为NA。瞧,运行
dt1$id我刚才问了一个问题,看。我感谢你的时间和努力!
set.seed(1L);
dt1 <- data.table(id=1:12,expand.grid(V1=1:3,V2=1:4),blah1=rnorm(12L));
dt2 <- data.table(id=13:18,expand.grid(V1=1:2,V2=1:3),blah2=rnorm(6L));
dt1;
##     id V1 V2      blah1
##  1:  1  1  1 -0.6264538
##  2:  2  2  1  0.1836433
##  3:  3  3  1 -0.8356286
##  4:  4  1  2  1.5952808
##  5:  5  2  2  0.3295078
##  6:  6  3  2 -0.8204684
##  7:  7  1  3  0.4874291
##  8:  8  2  3  0.7383247
##  9:  9  3  3  0.5757814
## 10: 10  1  4 -0.3053884
## 11: 11  2  4  1.5117812
## 12: 12  3  4  0.3898432
dt2;
##    id V1 V2       blah2
## 1: 13  1  1 -0.62124058
## 2: 14  2  1 -2.21469989
## 3: 15  1  2  1.12493092
## 4: 16  2  2 -0.04493361
## 5: 17  1  3 -0.01619026
## 6: 18  2  3  0.94383621
key <- paste0('V',1:2);
dt1[dt2,on=key,id:=i.id];
dt1;
##     id V1 V2      blah1
##  1: 13  1  1 -0.6264538
##  2: 14  2  1  0.1836433
##  3:  3  3  1 -0.8356286
##  4: 15  1  2  1.5952808
##  5: 16  2  2  0.3295078
##  6:  6  3  2 -0.8204684
##  7: 17  1  3  0.4874291
##  8: 18  2  3  0.7383247
##  9:  9  3  3  0.5757814
## 10: 10  1  4 -0.3053884
## 11: 11  2  4  1.5117812
## 12: 12  3  4  0.3898432