R 什么是「;“数据表”;执行此连接/合并的方式?

R 什么是「;“数据表”;执行此连接/合并的方式?,r,join,merge,left-join,data.table,R,Join,Merge,Left Join,Data.table,我有这样一个“字典”表: dict <- data.table( Nickname = c("Abby", "Ben", "Chris", "Dan", "Ed"), Name = c("Abigail", "Benjamin", "Christopher", "Daniel", "Edward") ) dict # Nickname Name # 1: Abby Abigail # 2: Ben Benjamin # 3:

我有这样一个“字典”表:

dict <- data.table(
  Nickname = c("Abby", "Ben", "Chris", "Dan", "Ed"),
  Name = c("Abigail", "Benjamin", "Christopher", "Daniel", "Edward")
)
dict
#    Nickname        Name
# 1:     Abby     Abigail
# 2:      Ben    Benjamin
# 3:    Chris Christopher
# 4:      Dan      Daniel
# 5:       Ed      Edward
dat <- data.table(
  Friend1 = c("Abby", "Ben", "Ben", "Chris"),
  Friend2 = c("Ben", "Ed", NA, "Ed"),
  Friend3 = c("Ed", NA, NA, "Dan"),
  Friend4 = c("Dan", NA, NA, NA)
)
dat
#    Friend1 Friend2 Friend3 Friend4
# 1:    Abby     Ben      Ed     Dan
# 2:     Ben      Ed      NA      NA
# 3:     Ben      NA      NA      NA
# 4:   Chris      Ed     Dan      NA
dat[, id := .I]
dat.m <- melt(dat, id.vars='id', variable.name='Friend', value.name='Nickname')
setkey(dict, Nickname)
dat.m[, Name := dict[Nickname, Name]]
> dat.m
    id  Friend Nickname        Name
 1:  1 Friend1     Abby     Abigail
 2:  2 Friend1      Ben    Benjamin
 3:  3 Friend1      Ben    Benjamin
 4:  4 Friend1    Chris Christopher
 5:  1 Friend2      Ben    Benjamin
 6:  2 Friend2       Ed      Edward
 7:  3 Friend2       NA          NA
 8:  4 Friend2       Ed      Edward
 9:  1 Friend3       Ed      Edward
10:  2 Friend3       NA          NA
11:  3 Friend3       NA          NA
12:  4 Friend3      Dan      Daniel
13:  1 Friend4      Dan      Daniel
14:  2 Friend4       NA          NA
15:  3 Friend4       NA          NA
16:  4 Friend4       NA          NA
这就是我想到的解决方案:

friend_vars <- paste0("Friend", 1:4)
friend_nicks <- paste0(friend_vars, ".Nickname")
friend_names <- paste0(friend_vars, ".Name")
setnames(dat, friend_vars, friend_nicks)
for (i in 1:4) {
  dat[, friend_names[i] := dict$Name[match(dat[[friend_nicks[i]]], dict$Nickname)], with = FALSE]
}

friend\u vars我没有想出一个与您的
结果完全匹配的解决方案,但您可能可以通过以下方式工作:

dict <- data.table(
  Nickname = c("Abby", "Ben", "Chris", "Dan", "Ed"),
  Name = c("Abigail", "Benjamin", "Christopher", "Daniel", "Edward")
)
dict
#    Nickname        Name
# 1:     Abby     Abigail
# 2:      Ben    Benjamin
# 3:    Chris Christopher
# 4:      Dan      Daniel
# 5:       Ed      Edward
dat <- data.table(
  Friend1 = c("Abby", "Ben", "Ben", "Chris"),
  Friend2 = c("Ben", "Ed", NA, "Ed"),
  Friend3 = c("Ed", NA, NA, "Dan"),
  Friend4 = c("Dan", NA, NA, NA)
)
dat
#    Friend1 Friend2 Friend3 Friend4
# 1:    Abby     Ben      Ed     Dan
# 2:     Ben      Ed      NA      NA
# 3:     Ben      NA      NA      NA
# 4:   Chris      Ed     Dan      NA
dat[, id := .I]
dat.m <- melt(dat, id.vars='id', variable.name='Friend', value.name='Nickname')
setkey(dict, Nickname)
dat.m[, Name := dict[Nickname, Name]]
> dat.m
    id  Friend Nickname        Name
 1:  1 Friend1     Abby     Abigail
 2:  2 Friend1      Ben    Benjamin
 3:  3 Friend1      Ben    Benjamin
 4:  4 Friend1    Chris Christopher
 5:  1 Friend2      Ben    Benjamin
 6:  2 Friend2       Ed      Edward
 7:  3 Friend2       NA          NA
 8:  4 Friend2       Ed      Edward
 9:  1 Friend3       Ed      Edward
10:  2 Friend3       NA          NA
11:  3 Friend3       NA          NA
12:  4 Friend3      Dan      Daniel
13:  1 Friend4      Dan      Daniel
14:  2 Friend4       NA          NA
15:  3 Friend4       NA          NA
16:  4 Friend4       NA          NA
dat[,id:=.I]
dat.m dat.m
id好友昵称名称
1:1友谊1艾比·阿比盖尔
2:2朋友1本本杰明
3:3朋友1本·本杰明
4:4朋友1克里斯·克里斯托弗
5:1朋友2本·本杰明
6:2与爱德华交友
7:3 Friend2娜娜
8:4与爱德华交友
9:1与爱德华成了朋友
10:2 Friend3 NA
11:3 Friend3娜娜
12:4朋友3丹·丹尼尔
13:1朋友4丹·丹尼尔
14:2 Friend4 NA
15:3 Friend4娜娜
16:4 Friend4 NA
变量
id
只是一个占位符,所以我可以将DT融化在base中,超级丑陋:

setkey(dict,Nickname)
dat[,paste(names(dat),"Name",sep="."):=lapply(.SD,function(x)dict[J(x)]$Name)]
setcolorder(dat,c(1,5,2,6,3,7,4,8))
dat
#    Friend1 Friend1.Name Friend2 Friend2.Name Friend3 Friend3.Name Friend4 Friend4.Name
# 1:    Abby      Abigail     Ben     Benjamin      Ed       Edward     Dan       Daniel
# 2:     Ben     Benjamin      Ed       Edward      NA           NA      NA           NA
# 3:     Ben     Benjamin      NA           NA      NA           NA      NA           NA
# 4:   Chris  Christopher      Ed       Edward     Dan       Daniel      NA           NA
cbind(dat, lapply(dat, function(x){dict$Name[match(x, dict$Nickname)]}))

   Friend1 Friend2 Friend3 Friend4          V2       NA     NA     NA
1:    Abby     Ben      Ed     Dan     Abigail Benjamin Edward Daniel
2:     Ben      Ed      NA      NA    Benjamin   Edward     NA     NA
3:     Ben      NA      NA      NA    Benjamin       NA     NA     NA
4:   Chris      Ed     Dan      NA Christopher   Edward Daniel     NA

使用
数据。表1.9.5

for (nm in names(dat)) {
    on = setattr("Nickname", 'names', nm)
    dat[dict, paste0(nm, ".Name") := i.Name, on=on]
}
我们可以使用
on=
而不是设置键来加入。现在可以使用
setcolorder()
对名称重新排序


除非绝对必要,否则我避免重塑数据。这就是“加入时更新”非常方便的地方。现在有了
on=
参数,我忍不住发布了一个答案:-)。

是的,我认为长格式更好。进行合并的标准方法是
setkey(dat.m,昵称);dat.m[dict,Name:=i.Name]
。OP也可以使用dcast(dat.m,id~Friend,value.var=c(“Name”,“昵称”))还原为宽格式。
,尽管它看起来仍然与它们所需的输出不完全相同。@Frank如果在
dict
中有未使用的元素,这个答案就不能很好地工作。考虑<代码> DATT @ SSDECONTROLL <代码> DAT.M[DICT] < /C> >将有更多行,是的,但是<代码> DAT.M./COD>不能以这种方式获得额外的行。如果你试着运行我的代码,然后运行
dat.m
,你会发现它只是在表中添加了一列——这样的合并不能添加行。我升级到1.9.5就是为了这个,我很高兴我这么做了。
on=
语法很棒!顺便问一下,如果您事先知道要从宽格式切换到长格式,一般来说,合并第一个和合并第二个,还是合并第一个和合并第二个更有效?太好了!我的猜测是融化+加入会更快(因为你只需要加入一次)。。就速度而言,melt通常是便宜的操作(如果正确实现的话)。另外:
i.*
语法记录在哪里?我在
[.data.table
:=
@ssdecontrol中找不到它我已经两年没有问过
I
的文档了,但是它似乎仍然不见了…@ssdecontrol看到了。你可以自由发布PR。我没有计划在短期内处理它。