根据第一个列值而不合并计算第二个数据表中的行

Use*_*321 3 r data.table

我承认问题的标题有点神秘,但请耐心等待.我有两个数据表,一个小,一个非常大,包含无用的信息.

第一个数据集(dt1)采用以下格式:

      CG     MG1     MG2
1:   49693 914569 4417756
2:   50422  22514   31343
3:   90543  90544 4531361
4:  142864 143471  143806
5:  386093   2149 4149104
6: 2674708  23921   24327
Run Code Online (Sandbox Code Playgroud)

所以它只包含数字,其中一些可以在第二个数据表中找到.第二个数据表(dt2)包含许多字段,但我需要的是ID.

      ID
1:   49693
2:   49693
3:   49693
4:   49693
5:   49693
6: 2674708
7: 2679818
8: 2680618
9:   49693
10: 2695042
Run Code Online (Sandbox Code Playgroud)

我想要做的是在dt1中再添加3个列,每个列指定dt2中是否有超过5行,ID分别等于CG1,MG1,MG2.我的最终结果将是:

     CG     MG1     MG2    CG_OK MG1_OK MG2_OK
1:   49693 914569 4417756     1      0      0
2:   50422  22514   31343     0      0      0
3:   90543  90544 4531361     0      0      0
4:  142864 143471  143806     0      0      0
5:  386093   2149 4149104     0      0      0
6: 2674708  23921   24327     0      0      0
Run Code Online (Sandbox Code Playgroud)

在CG_OK中有一个1,因为对于CG 49693,我们可以在dt2中找到具有相同ID的6行.

我可以实现结果的方法:子集dt2只包含可以在CG,MG1和MG2中找到的值,然后计算每个值的行,然后以某种方式合并.

我的问题是,是否有更好的(或代码方面更短)方式?有点像(我不知道):

dt1[, CG_OK := ifelse(nrow(dt2[ID == CG]) > 5, 1, 0)]
Run Code Online (Sandbox Code Playgroud)

Jaa*_*aap 7

附:

dt1[, paste0(names(dt1),'_OK') := lapply(.SD, function(x) as.integer(x %in% unique(dt2$ID))), .SDcols = 1:3][]
Run Code Online (Sandbox Code Playgroud)

你得到:

        CG    MG1     MG2 CG_OK MG1_OK MG2_OK
1:   49693 914569 4417756     1      0      0
2:   50422  22514   31343     0      0      0
3:   90543  90544 4531361     0      0      0
4:  142864 143471  143806     0      0      0
5:  386093   2149 4149104     0      0      0
6: 2674708  23921   24327     1      0      0
Run Code Online (Sandbox Code Playgroud)

如果不需要转换为整数:

dt1[, paste0(names(dt1),'_OK') := lapply(.SD, `%in%`, unique(dt2$ID)), .SDcols = 1:3]
Run Code Online (Sandbox Code Playgroud)

或者更具可读性:

cols <- names(dt1)
dt1[, paste0(cols,'_OK') := lapply(.SD, `%in%`, unique(dt2$ID)), .SDcols = cols]
Run Code Online (Sandbox Code Playgroud)

因为要检查所有列,所以不一定需要指定.SDcols参数.所以,最短的版本是:

dt1[, paste0(cols,'_OK') := lapply(.SD, `%in%`, unique(dt2$ID))]
Run Code Online (Sandbox Code Playgroud)