匹配和替换部分字符串的优雅方式

时间:2018-10-05 07:00:20

标签: r data.table

我有两个数据表,例如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)

有什么方法可以优雅地加快速度吗?

5 个答案:

答案 0 :(得分:3)

这是基本的R方法。我们可以使用最后一个破折号右边的数字在第一个List数据表中创建一个relationships(path)列。然后,我们可以x上的两个数据表dt,并最终连接您期望的merge结果。

x

Demo

答案 1 :(得分:3)

base R,sprintf + sub

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 )

请注意:仅在示例中订购了dtdt1时,我的解决方案才有效。这意味着每个第一行都是相关的,等等。如果不是这种情况,请考虑将@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