从另一个表中匹配一个表的列,以获得R中主表中所需的列

g9icjywg  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(99)

我有这个数据表。

library(data.table)
class<- c("a","c","v","f","r","b","t","o");
value<-c(0.76,  0.91,   1.94,   0.37,   1.35,   0.75,   1.95,   1.69);
vehicle<-c("we",    "df",   "rt",   "yh",   "uj",   "er",   "ed","we")
carbon<-c(0.984,    0.27,   0.419,  0.469,  0.132,  0.865,  0.562,  0.133)
cap<-c(3,   2,  1,  6,  "y",    "t",    4,  6)
up<-c(4,    2,  3,  "d",    "t",    "y",    "u",    "i")
down<-c("t",    "e",    "r",    3,  4,  5,  2,  1)
amt<-c( 34, 23, 12, 67, 87, 43, 23, 12)
df<-data.table(class,value,vehicle,carbon,cap,up,down,amt)

这是另一个Map表

up<-c("d","i",4)
vehicle<-c("yh",    "we",   "we")
exercise<-c("ty",45,    "k")
map<-data.table(cbind(vehicle,up,exercise))

我需要df表中的exercise
我目前正在使用这段代码,它产生了预期的结果。我很满意

df[,names(map)[length(names(map))]:= 
                map$exercise[match(do.call(paste0,df[, which(names(df) %in% names(map)[1:(ncol(map)-1)]),with = FALSE]),
                                                   do.call(paste0,map[,1:(ncol(map)-1)]))] ]

基本上这段代码的作用是。
1.在主表中标识Map表中的列。
1.将这些列连接起来。
1.将这些连接列与Map表的连接列进行匹配。
1.从Map表中索引所需列并将其固定到主表。
所以我们想要的结果是

> df$exercise
[1] "k"  NA   NA   "ty" NA   NA   NA   "45"

但有时Map表的列顺序会更改。
例如,更改的Map表是注意,现在的顺序是向上,然后是车辆。在这种情况下,上述代码将不会产生预期的结果,事实上,它将是所有NA。

up<-c("d","i",4)
vehicle<-c("yh",    "we",   "we")
exercise<-c("ty",45,    "k")
map<-as.data.frame(cbind(up,vehicle,exercise))
setDT(map)

所以我的代码只在Map表中的列顺序与主表中的列顺序相同时才起作用。如果我的代码可以改变,以执行相同的结果,但考虑到列的顺序。理想情况下会希望它尽可能动态。
Map表可以具有与主表中一样多的列,以及需要插入到主表中的附加列。
如果您需要任何进一步的澄清,请发表评论。我将不胜感激,如果我的代码可以编辑和提供。任何其他代码也是受欢迎的。我更喜欢数据.表格包使用.

kpbwa7wx

kpbwa7wx1#

我认为这里最大的问题不是merge/join的基本机制,而是当要连接的列未知时,以及要连接到df的列也未知时。
我认为这是一个合理的方法:

df <- data.table::as.data.table(structure(list(class = c("a", "c", "v", "f", "r", "b", "t", "o"), value = c(0.76, 0.91, 1.94, 0.37, 1.35, 0.75, 1.95, 1.69), vehicle = c("we", "df", "rt", "yh", "uj", "er", "ed", "we"), carbon = c(0.984, 0.27, 0.419, 0.469, 0.132, 0.865, 0.562, 0.133), cap = c("3", "2", "1", "6", "y", "t", "4", "6"), up = c("4", "2", "3", "d", "t", "y", "u", "i"), down = c("t", "e", "r", "3", "4", "5", "2", "1"), amt = c(34, 23, 12, 67, 87, 43, 23, 12)), row.names = c(NA, -8L), class = c("data.table", "data.frame" )))
map <- data.table::as.data.table(structure(list(up = c("d", "i", "4"), vehicle = c("yh", "we", "we"), exercise = c("ty", "45", "k")), class = c("data.table", "data.frame"), row.names = c(NA, -3L)))

(same <- intersect(names(map), names(df)))
# [1] "up"      "vehicle"
(diff <- setdiff(names(map), names(df)))
# [1] "exercise"
if (length(same) && length(diff)) 
  df[map, c(diff) := mget(diff), on = same]
#     class value vehicle carbon    cap     up   down   amt exercise
#    <char> <num>  <char>  <num> <char> <char> <char> <num>   <char>
# 1:      a  0.76      we  0.984      3      4      t    34        k
# 2:      c  0.91      df  0.270      2      2      e    23     <NA>
# 3:      v  1.94      rt  0.419      1      3      r    12     <NA>
# 4:      f  0.37      yh  0.469      6      d      3    67       ty
# 5:      r  1.35      uj  0.132      y      t      4    87     <NA>
# 6:      b  0.75      er  0.865      t      y      5    43     <NA>
# 7:      t  1.95      ed  0.562      4      u      2    23     <NA>
# 8:      o  1.69      we  0.133      6      i      1    12       45

当然,当mapdf中存在意外列时,可能会出现几种错误。
我添加了if (length(same) && length(diff))部分,这样我们就不会无意中尝试在零列上进行联接或在没有列的情况下进行合并。

  • 编辑 *:@MerijnvanTilborg说df[map, on=.NATURAL]也可以工作.我还没有测试它的所有角落,但它似乎按预期工作,认识到我们需要捕获它的返回值:
map[df, on = .NATURAL] # right output, but ...
df                     # ... but df is unchanged, so ...
df <- map[df, on = .NATURAL]

重复调用此函数会做正确的事情(即,仅此而已)。

相关问题