2015-06-19 55 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