2015-06-19 49 views
1

我正在寻找一种方法来使用R中的查找和替换功能来替换字符串的整个值,而不仅仅是字符串的匹配部分。我有一个包含很多(很长)名字的数据集,我正在寻找一种有效的方式来查找和更改它们的值。查找并替换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) 

然而,这导致代以 “EXP”只有与“体验”相匹配的字符串部分,并且保留了长名称的其余部分(粗体字母f或清晰度):

“Overall.speaking..do.you.prefer.to.try.out.new。 EXP ..like.trying.things.and.meeting.new.people..or.do.you.prefer.familiar.situations.and.faces。”

在这种情况下,因为字符串包含“体验”,它应该被替换为“exp”

有没有办法告诉gsub或其他函数来替换整个值?我看了很多教程,它看起来像函数只能在字符串或整个值,但不在两者之间

+1

那么,如果找到“experience”,返回“exp”,否则返回整个字符串? @离得越来越近@rawr @ – Frank

+0

!但很多字符串名称仍然保持不变。 – tom

+0

@frank是的。所以,只有在字符串中找到该模式才能替换该值。我将通过大量长名称值进行搜索。 – tom

回答

4

您可以使用gsub如下:

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

此正则表达式匹配任何字符0次或更多次(即.*),其次是“经验”的字符串,后跟任意字符0以上倍。

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

+0

嗯,所以也许我没有创建一个很好的例子。我在数据集中进行的替换使用'gsub(“*。experiences。*”,“exp”,names(fs)',其中名称(fs)是所有标题名称列的向量。代码向量,它只会导致字符串值的部分替换“”一般来说,我不知道为什么列向量会有所不同。 – tom

+0

that worked!好眼睛其他坦白!学习目的问题:做什么*做?我有点熟悉正则表达式,我不承认 – tom

+1

哦,'.'是“任何字符”和'*'是“任意次数”:)对不起,我已经删除了我的评论,认为这是错误的。顺便说一句,反引号(在我的键盘上的波形符号按钮上)用于注释中的代码格式。 – Frank

5

由于知道所需的值(“exp”),所以不需要修改字符串gsub

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 
+1

关于字符串替换与修改相关速度差异的好处! – Jota

+2

我不是弗兰克,但如果你在'system.time(gsub(“。* experience。*”,“exp”,ss))中使用'perl = TRUE'',它会快两倍,我至少 – rawr

+1

@rawr坦率地说,这是效率的另一个好处。 - 弗兰克(紫色) – Jota

1

gsub()被用于替代与另一个字符串特定字符串。在上面的代码,如果你做到以下几点,你的整个字符串修改exp

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

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

res1 <- grep("pattern",string) 

为您提供模式的所有线条,并在replace()中使用。

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

正如我上面提到的,我想我搞砸了创建我的例子。我正在向gsub应用名称(df),以便r通过具有模式匹配的字符串的标头名称向量查找并替换该对象。您的代码适用于此示例,但不适用于来自数据框的矢量。我不知道这种不同的存在,但我应该创造一个更好的例子 – tom

+1

正如@Frank(绿色gravatar)所示,在这里不需要sapply或循环。感谢您指出替换()需要向量:) – Shiva