使用 data.table 将 table 中的列值替换为基于 R 中匹配项的查找值

Replace column values in table with values from lookup based on matches in R using data.table

我想用 lookup 列中匹配的相应值替换 table 列中的值。我通过 data.table 包“按引用分配”实现了这一点,一个接一个地取一个值(并且它是替换值),但我认为我可以做一些更模块化的事情。

总而言之,我是这样做的:

# Build a table and a lookup
code<- c("ABC","EBC","ABC","EBC","OOO","PPP","ABC")
sn <- c(1:7)
old<- c("ABC","EBC")
new<- c("CBa","CBe")

lookup <- data.frame(old,new)
table <-data.frame(code,sn)

# Set data.table as TRUE for both
setDT(table)
setDT(lookup)

# Attempt reassignment
table[code %in% lookup$old, code := lookup$new[which(lookup$old==code)]]
table

..我明白了:

> table
   code sn
1:  CBa  1
2:  CBe  2
3: <NA>  3
4: <NA>  4
5:  OOO  5
6:  PPP  6
7: <NA>  7

然而,我真正希望的是这样的结果:

> table
   code sn
1:  CBa  1
2:  CBe  2
3:  CBa  3
4:  CBe  4
5:  OOO  5
6:  PPP  6
7:  CBa  7

本质上:替换是根据查找分配的所有值(不仅仅是前两个)进行的。我错过了什么?我曾尝试寻找其他解决方案,但建议似乎并不是我想要的。感谢任何答案。

我们可以从 table 中加入 on 'code' 和 'old' 并分别查找

table[lookup, code := new, on = .(code = old)]

-输出

 table
   code sn
1:  CBa  1
2:  CBe  2
3:  CBa  3
4:  CBe  4
5:  OOO  5
6:  PPP  6
7:  CBa  7

基础 R 选项可以工作(但强烈推荐 ,超级优雅!)

transform(
  table,
  code = replace(
    code,
    code %in% lookup$old,
    setNames(lookup$new, lookup$old)[code][code %in% lookup$old]
  )
)

这给出了

   code sn
1:  CBa  1
2:  CBe  2
3:  CBa  3
4:  CBe  4
5:  OOO  5
6:  PPP  6
7:  CBa  7

或更长的 data.table 选项

> lookup[table, on = .(old = code)][, new := fcoalesce(new, old)][, old := NULL][]
   new sn
1: CBa  1
2: CBe  2
3: CBa  3
4: CBe  4
5: OOO  5
6: PPP  6
7: CBa  7