【问题标题】:How to replace one substring with different substrings in R?如何用R中的不同子串替换一个子串?
【发布时间】:2016-08-04 17:37:10
【问题描述】:

我有一个字符串向量,我想用不同的子字符串替换所有字符串中的一个公共子字符串。我在 R 中这样做。例如:

input=c("I like fruits","I like you","I like dudes")
# I need to do something like this
newStrings=c("You","We","She")
gsub("I",newStrings,input)

所以输出应该是这样的:

"You like fruits"
"We like you"
"She like dudes"

但是,gsub 只使用 newStrings 中的第一个字符串。有什么建议么? 谢谢

【问题讨论】:

  • 哇,一个问题有这么多不同的解决方案,谢谢大家!
  • 您只想替换字符串的开头还是处处的字符串?如果I 在一个字符串中多次出现会怎样?
  • @DavidArenburg 好点,我想考虑“我”可能在任何地方出现任何次数的情况。我想我的例子有点误导。
  • 如果“I”出现在句子中间,会导致结果显示不正确的英文。

标签: r


【解决方案1】:

你可以使用stringr

stringr::str_replace_all(input, "I" ,newStrings)

[1] "You like fruits" "We like you"    
[3] "She like dudes"

或如@David Arenburg 建议的那样:

stringi::stri_replace_all_fixed(input, "I", newStrings)

基准测试

library(stringi)
library(stringr)
library(microbenchmark)

set.seed(123)
x <- stri_rand_strings(1e3, 10)
y <- stri_rand_strings(1e3, 1)

identical(stringi::stri_replace_all_fixed(x, "I", y), stringr::str_replace_all(x, fixed("I") , y))
# [1] TRUE
identical(stringi::stri_replace_all_fixed(x, "I", y), diag(sapply(y, gsub, pattern = "I", x = x, fixed = TRUE)))
# [1] TRUE
identical(stringi::stri_replace_all_fixed(x, "I", y), mapply(gsub, "I", y, x, USE.NAMES = FALSE, fixed = TRUE))
# [1] TRUE

microbenchmark("stingi: " = stringi::stri_replace_all_fixed(x, "I", y),
               "stringr (optimized): " = stringr::str_replace_all(x, fixed("I") , y),
               "base::mapply (optimized): " = mapply(gsub, "I", y, x, USE.NAMES = FALSE, fixed = TRUE),
               "base::sapply (optimized): " = diag(sapply(y, gsub, pattern = "I", x = x, fixed = TRUE)))

# Unit: microseconds
#                       expr        min          lq        mean      median          uq        max neval cld
#                   stingi:     132.156    137.1165    171.5822    150.3960    194.2345    460.145   100  a 
#      stringr (optimized):     801.894    828.7730    947.1813    912.6095    968.7680   2716.708   100  a 
# base::mapply (optimized):    2827.104   2946.9400   3211.9614   3031.7375   3123.8940   8216.360   100  a 
# base::sapply (optimized):  402349.424 476545.9245 491665.8576 483410.3290 513184.3490 549489.667   100   b

【讨论】:

  • 不错!这比我的答案更紧凑。
  • @MikeyMike,你的方法更通用。
  • 如果你不介意的话,我很快就会用基准编辑你的帖子
【解决方案2】:

mapply() 在这些情况下非常有用:

mapply(sub, "I", newStrings, input, USE.NAMES = FALSE,fixed=T)
# [1] "You like fruits" "We like you"     "She like dudes" 

【讨论】:

  • 我将您的代码编辑为 (1) mapply() 以避免 unlist(),(2) USE.NAMES = FALSE 以避免 unname(),并且 (3) 删除了不必要的匿名函数。现在一切都在一个通话中。
  • 也可以加fixed = TRUE
  • 当然,把那个也扔进去!哈哈。我也会更改为sub()。我会让他弄清楚其余的;)
  • 感谢您的更新 - 这更干净!我编辑了我的帖子以包含fixed=T,但忽略了sub()。我想他可能想替换“我”的所有实例
【解决方案3】:

您可以为此使用sapply

diag(sapply(newStrings,gsub,pattern="I",x=input))

【讨论】:

  • 这在内存和性能方面都非常低效
猜你喜欢
  • 2015-11-09
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2014-05-18
  • 2011-04-06
  • 1970-01-01
相关资源
最近更新 更多