我有两个数据表,例如dt和dt1
dt <- data.table(s=c("AA-AA-1", "BB-BB-2", "CC-CC-3"))
s
1 AA-AA-1
2 BB-BB-2
3 CC-CC-3
dt1 <- data.table(x=c(1,2,3), name=c("AA", "BB", "CC"))
x name
1: 1 AA
2: 2 BB
3: 3 CC
我需要用dt的dt1列中s&x col的最后一个连字符后的数字来匹配dt的s列中的dt的s列中的字符串部分,以便dt变成这样。
s
1: AA-AA-AA
2: BB-BB-BB
3: CC-CC-CC
我知道我们可以通过拆分s和进行匹配
split <- lapply(strsplit(as.character(dt$s), split="-"), tail, n=1)
dt1$name[match(dt$split, dt1$x)
有什么方法可以优雅地加快速度吗?
答案 0 :(得分:3)
这是基本的R方法。我们可以使用最后一个破折号右边的数字在第一个List
数据表中创建一个relationships(path)
列。然后,我们可以x
上的两个数据表dt
,并最终连接您期望的merge
结果。
x
答案 1 :(得分:3)
mapply(sprintf, sub("[^-]+$", "%s", dt$s), dt1$name)
# AA-AA-%s BB-BB-%s CC-CC-%s
# "AA-AA-AA" "BB-BB-BB" "CC-CC-CC"
我假设两个数据帧的匹配顺序都相同(如示例中所示)。如果不是,则需要先进行匹配,例如:
mapply(sprintf, sub("-.?$", "-%s", dt$s), dt1$name[match(gsub("[^0-9]","", dt$s), dt1$x)])
答案 2 :(得分:3)
我会采用简单的方法:
dt1[dt[, .(x = as.integer(sub('.*-', '', s)), str = sub('[^-]+$', '', s))],
on = .(x), .(s = paste0(str, name))]
# s
#1: AA-AA-AA
#2: BB-BB-BB
#3: CC-CC-CC
答案 3 :(得分:0)
这是一种稍微通用的方法。
mapply(function(pat, repl, src){ sub(pat, repl, src) }, pat = dt1$x, repl = dt1$name, src = dt$s )
#[1] "AA-AA-AA" "BB-BB-BB" "CC-CC-CC"
如果您说您总是要在之后替换-(连字符),那么可以简化为:
mapply(function(repl, src){ sub("(?<=-)[^-]+$", repl, src, perl = T) }, repl = dt1$name, src = dt$s )
请注意:仅在示例中订购了dt
和dt1
时,我的解决方案才有效。这意味着每个第一行都是相关的,等等。如果不是这种情况,请考虑将@Tims(正在合并...)和我的解决方案结合起来。
因此,这是使用蒂姆一些想法的坚如磐石的解决方案:
dt <- data.table(s=c("AA-AA-1", "BB-BB-2", "CC-CC-3"))
dt1 <- data.table(x=3:1, name=c("CC", "BB", "AA")) # note the order is not right.
dt$x <- sub(".*-", "", dt$s)
dt <- merge.default(dt, dt1, by="x")
dt$endResult <- mapply(function(repl, src){ sub("(?<=-)[^-]+$", repl, src, perl = T) }, repl = dt$name, src = dt$s )
答案 4 :(得分:-1)
如果按照您的示例对它们进行了适当的排序,则可以使用stringr::str_replace
:
library(stringr)
dt[,s := str_replace(s,as.character(dt1$x),dt1$name)]
dt
# s
# 1: AA-AA-AA
# 2: BB-BB-BB
# 3: CC-CC-CC