基于另一个数据表的data.table映射

3

我有两个数据(.xlsx),DT1DT2。我想在DT1中创建一个名为newcol的新列,该列基于DT1中的原始列,并与DT2中的列进行映射。
我知道这很模糊,所以我在这里解释更多:
首先,这是我的两个数据。

DT1
code    type  
AH1     AM
AS5     AM
NMR     AM
TOS     AM
IP      AD
CC      ADCE
CA      Wa

DT2
code    year   month  
AH1     2011   2
AH1     2011   5
AS5     2012   7
AS5     2012   6
AS5     2013   3
CC      2014   6
CA      2016   11

其次,在DT2中,列yearmonth在这个问题中不重要。我们不需要考虑它。
第三,我想要的结果是:

DT2
code    year   month   newcol
AH1     2011   2       AM
AH1     2011   5       AM
AS5     2012   7       AM
AS5     2012   6       AM
AS5     2013   3       AM
CC      2014   6       ADCE
CA      2016   11      Wa

DT2中的newcol是基于DT1数据创建的。
我看到了一个类似于DT2[DT1, ...]的语法来解决这个问题,但我忘记了。能帮忙吗?

数据

DT1 <- "  code    type  
1:        AH1     AM
2:        AS5     AM
3:        NMR     AM
4:        TOS     AM
5:        IP      AD
6:        CC      ADCE
7:        CA      Wa
"
DT1 <- read.table(text=DT1, header = T)
DT1 <- as.data.table(DT1)

DT2 <- "code    year   month  
1: AH1     2011   2
2: AH1     2011   5
3: AS5     2012   7
4: AS5     2012   6
5: AS5     2013   3
6: CC      2014   6
7: CA      2016   11
"
DT2 <- read.table(text=DT2, header =T)
DT2 <- as.data.table(DT2)

附注:另外,在Excel中,有一个函数VLOOKUP可以解决这个问题:

# Take first obs. as an example. 
DT2
code    year   month  
AH1     2011   2
# newcol is column D. So in D2, we type:
=VLOOKUP(TRIM(A1), 'DT1'!$A$2:$A$8, 2, FALSE)

根据@akrun答案下的评论进行更新。
我的原始数据框 DT1 有86行,DT2 有451125行。我使用了@akrun的回答,DT2 缩减到了192409行。很奇怪。 DT2$code 中没有任何缺失值。我不知道为什么会这样。

length(unique(DT1$code1)) 
[1] 86
length(unique(DT2$code))
[1] 39

table(DT1$code1) 
AHI AHI002 AHI004 AHI005 AHS002 AHS003 AHS004 AHS005    AMR AMR002 AMR003 AMRHI3   CARD   CCRU  HPA01  HWPA1 HWPA1T    IOA  IOA01 
 1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1 
IOA01T IPA010 IPA011 IPA012 IPA013 IPA014 IPACC3 IPACC4 IPACC5 IPACC6   IPAR  IPAR2 IPARK2 IPARKI   NAHI  NAHI2   NAMR  NAMR2    NCC 
 1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1 
NCC2   NCC5  NCC5T  NNAHI NNAHI2  NNAMR NNAMR2     PL    PL2   PLFI    REI    SPA SPA001   SPA3   TADS  TADS2   TAHI  TAHI2   TAHS 
 1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1 
TAHS2   TAMB  TAMB2   TAMD  TAMD2   TAMR  TAMR2  TBURN TBURN2   TCCR   TFPS    TFS   TFS2    THE  THIBN THIBN2   TICU  TICU2   TIPA 
 1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1      1 
TIPA2  TIPAK TIPAK2   TNCC    TOS   TOS2   TSAO  TSAO2   TSPA    WED 
 1      1      1      1      1      1      1      1      1      1 

table(DT2$code)
AHI002 AHI005 AHS002 AHS005 AMR    AMR003 Card   HPA01  HWPA1  HWPA1T IOA01  IOA01T IPA011 IPA012 IPA013 IPA014 IPACC3 IPACC4 IPACC5 
19408  12215  34184  12226  19408  12215  19408   7344   9198    405   9198    405  12215   5137   1148   2853  31703   9198   7878 
IPACC6 IPAR   IPAR2  IPARK2 IPARKI NAHI   NAHI2  NAMR   NAMR2  NCC2   NCC5   NCC5T  NNAHI  NNAHI2 NNAMR  NNAMR2 PL     PL2    SPA    
9668  41909   9643   2362   2967  10018   3589  10018   3589   7878   2845    536  14776   8104  14754   8118  18624   8302  40856 
SPA3   
6823 

1
尝试将代码设置为两个数据表的键,然后使用DT1索引DT2,例如DT2[DT1] - din
2
忘记了的话,你可以在 ?data.table 底部查看示例。 - Frank
2个回答

6
我们可以使用data.table中的join完成此操作。
library(data.table)
DT2[DT1, on = .(code), nomatch = 0]
#   code year month type
#1:  AH1 2011     2   AM
#2:  AH1 2011     5   AM
#3:  AS5 2012     7   AM
#4:  AS5 2012     6   AM
#5:  AS5 2013     3   AM
#6:   CC 2014     6 ADCE
#7:   CA 2016    11   Wa

5
在这种情况下,DT2[DT1, on = .(code = code1), nomatch = 0]的意思是将数据表DT1和DT2按照列code和code1进行连接(内连接),nomatch=0表示不返回未匹配的行。 - akrun
2
另一个小问题:nomatch = 0 是什么意思?谢谢。 - Peter Chen
3
否则,它将获取所有不匹配的行。 - akrun
3
如果你想学习R语言的某些东西,可以向@akrun学习。 - M--
1
@PeterChen 我的意思是,如果“code”列在两个数据集中的某些观测值中具有频率>1,则可能会发生这种情况。最好从两个数据集的子集中进行检查,并查看是否获得了预期结果。 - akrun
显示剩余12条评论

3

您可以在基础 R 中使用 merge

DT2 <- (merge(DT1, DT2, by = 'code'))

注意:它还会按照'code'列进行排序。

您也可以使用plyr包:

DT2 <- plyr::join(DT2, DT1, by = "code")

因为您对使用data.table包感兴趣:

library(data.table)
DT2 <- data.table(DT2, key='code')
DT1 <- data.table(DT1, key='code')

DT2[DT1]

或者使用qdap软件包:
DT2$type <- qdap::lookup(DT2$code, DT1)

你的答案很出色。然而,我的数据非常大,所以 data.tableplyrdplyr 更快。 - Peter Chen
@PeterChen 已更新,增加了两个选项包括 data.table - M--
qdapdata.table更快吗? - Peter Chen
1
不,data.tablemerge是最快的。我现在无法检查,但您可以使用microbenchmark :: microbenchmark(function1,function2,times = 1000)来检查执行时间。 - M--

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接