【问题标题】:Find and replace entire value in R在 R 中查找和替换整个值
【发布时间】:2015-06-19 19:54:17
【问题描述】:

我正在寻找一种方法来使用 R 中的查找和替换函数来替换字符串的整个值,而不仅仅是字符串的匹配部分。我有一个包含很多(非常)长名称的数据集,我正在寻找一种有效的方法来查找和更改它们的值。

因此,例如,我尝试更改整个字符串

string <- "Generally.speaking..do.you.prefer.to.try.out.new.experiences.like.trying.things.and.meeting.new.people..or.do.you.prefer.familiar.situations.and.faces."

"exp"

使用此代码

string <- gsub("experiences", "exp", string)

但是,这会导致仅将字符串中与“experiences”匹配的部分替换为“exp”,并保留长名称的其余部分(为清楚起见加粗):

“一般来说.speaking..do.you.prefer.to.try.out.new.exp..like.trying.things.and.meeting.new.people..or. do.you.prefer.familiar.situations.and.faces."

在这种情况下,因为字符串中包含“经验”,所以应该将其替换为“经验”。

有没有办法告诉 gsub 或其他一些函数来替换整个值?我看了很多教程,似乎函数只能在字符串或整个值上运行,而不是在两者之间。

【问题讨论】:

  • 那么,如果找到“experiences”,则返回“exp”,否则返回整个字符串?
  • @rawr 离得更近了!但是很多字符串名称仍然完好无损。
  • @frank 是的。因此,仅当在字符串中找到模式时才替换该值。我将搜索很多长名称的值。

标签: regex r replace


【解决方案1】:

无需使用gsub 修改字符串,因为您知道所需的值(“exp”)。

s = c(string,"bah","egad.experiences")

replace(s,grep("experiences",s),"exp")
# [1] "exp" "bah" "exp"

速度。这比其他@Frank 回答中的字符串修改要快一点。

(感谢@rawr 指出我们都应该打开 perl 解析。)

ss <- c(replicate(1e6,s))
system.time(replace(ss,grep("experiences",ss,perl=TRUE),"exp"))
#    user  system elapsed 
#     0.6     0.0     0.6 
system.time(gsub(".*experiences.*", "exp", ss,perl=TRUE))
#    user  system elapsed 
#    2.39    0.00    2.38

去掉每个答案中的替换操作,看起来被匹配的不同模式弥补了大部分差异(与我的预期相反,在我上次编辑中看到):

system.time(grep("experiences",ss,perl=TRUE))     # used in my answer
#    user  system elapsed 
#    0.64    0.00    0.64
system.time(grep(".*experiences.*",ss,perl=TRUE)) # used in purple-gravatar @Frank's answer
#    user  system elapsed 
#    1.82    0.00    1.82 

【讨论】:

  • 关于字符串替换与修改所涉及的速度差异的好点!
  • 我不是弗兰克,但如果你在system.time(gsub(".*experiences.*", "exp", ss)) 中使用perl = TRUE,至少对我来说会快两倍
  • @rawr 坦率地说,这是效率方面的另一个优点。 - 弗兰克(紫色)
  • @rawr 谢谢;添加。唉,坦率和最优并不总是一致的。使用 perl,我的最后一点被颠倒了,所以我也对它进行了大量编辑。
【解决方案2】:

你可以使用gsub如下:

 gsub(".*experiences.*", "exp", string, perl=TRUE) 
 # As @rawr notes, set perl=TRUE for improved efficiency

此正则表达式匹配任何字符 0 次或多次(即.*)后跟“经验”,再后跟任何字符 0 次或多次的字符串。

在这种情况下,您仍将整个匹配替换为“exp”,但通过使用正则表达式,您可以扩展匹配的定义(从“experience”到“.*experience.*”)以实现所需的替换。

【讨论】:

  • 嗯,所以也许我没有创建一个很好的例子。我在我的数据集上所做的替换使用'gsub(“.experiences.”,“exp”,names(fs)',其中names(fs)是所有标题名称的列的向量.当我将代码应用于向量时,它只会部分替换字符串值““Generally.speaking..do.you.prefer.to.try.out.newexp””。我不知道为什么是一列矢量会有所不同。
  • 成功了!其他坦率的好眼光!学习目的的问题:.* 做什么?我对正则表达式有点熟悉,但我不知道
  • 哦,. 是“任意字符”,* 是“任意次数” :) 抱歉,我已经删除了我的评论,认为这是错误的。顺便说一句,反引号(在我键盘上的波浪号按钮上)用于在 cmets 中进行代码格式化。
【解决方案3】:

gsub() 用于将特定字符串替换为另一个字符串。在上面的代码中,如果您执行以下操作,您的整个字符串将更改为exp

result <- gsub(string, "exp", string)

但是,如果你使用grep()replace(),你会得到你想要的结果。

res1 <- grep("pattern",string)

为您提供带有该模式的所有行并在replace() 中使用它。

res_new <- replace(string,res1,"exp")

【讨论】:

  • 如上所述,我想我在创建示例时搞砸了。我将 gsub 应用于 names(df),以便 r 通过标题名称向量查找具有模式匹配的字符串并仅替换该对象。您的代码适用于此示例,但不适用于数据帧中的向量。我不知道存在这样的不同,但我应该创造一个更好的例子
  • 正如@Frank(green gravatar) 建议的那样,这里不需要 sapply 或循环。感谢您指出 replace() 采用向量 :)
【解决方案4】:

您也可以简单地使用gsub() 并在模式之前和之后添加.*,如下所示:

string<-"TransRights"
gsub(".*sR.*","HumanRights",string)

结果是

HumanRights

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 2010-12-19
    • 2019-10-29
    • 1970-01-01
    • 2011-12-08
    • 2018-07-21
    • 1970-01-01
    相关资源
    最近更新 更多