2011-07-18 117 views
1

我想從一組全名(後綴和全名都是字符向量)中刪除一組後綴。使用兩個for()循環和gsub()這很容易,但似乎應該有一個更有效的方法(無論是在代碼行還是時鐘循環中)。使用rapply從字符名稱向量中的字符向量

我的第一個想法是rapply(),但我不能得到它的工作。也許for()循環是最好的方法,但在這一點上我有興趣更好地瞭解rapply()

這裏是for()循環版本。

names.full <- c("tom inc", "dick co", "harry incorp", "larry inc incorp", "curly", "moe") 
suffix <- c("inc", "incorp", "incorporated", "co", "company") 
suffix <- paste(" ", suffix, "$", sep = "") 

# with loops 
names.abbr <- names.full 
for (k in seq(2)) { 
    for (i in seq(length(names.abbr))) { 
     for (j in seq(length(suffix))) { 
      names.abbr[i] <- gsub(suffix[j], "", names.abbr[i]) 
     } 
    } 
} 

而我的失敗rapply()版本。

# with rapply 
inner.fun <- function(y, x) { 
    rapply(as.list(x), function(x) gsub(y, "", x), how = "replace") 
} 
names.abbr.fail <- unlist(rapply(as.list(suffix), inner.fun, x = names.full, how = replace)) 

其中提供了以下錯誤:

> names.abbr.fail <- unlist(rapply(as.list(suffix), inner.fun, x = names.full, how = replace)) 
Error in match.arg(how) : 'arg' must be NULL or a character vector 
+0

錯誤是我認爲,因爲你沒有在你的'inner.fun'中引用「replace」。不知道如何用'rapply'做到這一點,但我相信有比循環更好的方法... – joran

回答

3

在你的榜樣,你最終只會刪除所有,但第一個字。這是很容易與

sub(" .*$", "", names.full) 

做,但更普遍的regexpr模式是一樣的東西"(suffix1|suffix2)"具有所有的後綴。

由於您似乎想要從"larry inc incorp"中刪除一個字符串中的多個後綴,因此您需要類似"(suffix1| suffix2)+$"之類的內容。

然後,您可以簡單地將它應用於names.full(我將「moe」改爲「moe money」以顯示「第一個字」解決方案失敗的情況)。這將是這個樣子:

names.full <- c("tom inc", "dick co", "harry incorp", 
    "larry inc incorp", "curly", "moe money") 
suffix <- c("inc", "incorp", "incorporated", "co", "company") 

pattern <- paste("(", paste(" ", suffix, collapse="|", sep=""), ")+$", sep="")  
sub(pattern, "", names.full) 
[1] "tom"  "dick"  "harry"  "larry"  "curly"  "moe money" 

順便說一下,如果你不想取代任何東西,但後綴,sub可能是一個更適合比gsubgsub通常用來取代幾個實例一個詞內的模式的)。

1

你真的需要使用for循環?我認爲你應該能夠在gsub中使用反向引用來提取你想要的內容。

  • \\w匹配0-9,A-Z和a-z範圍內的任何字符。
  • +與前一個字符匹配1次或更多次。
  • ()允許我們回溯參考以後在 以內的任何正則表達式。
  • .匹配任何字符的所有字符,而*匹配 前面的字符0或更多次。

把上述所有一起給我們:

gsub("(\\w+)(.*)", "\\1", names.full) 

> gsub("(\\w+)(.*)", "\\1", names.full) 
[1] "tom" "dick" "harry" "larry" "curly" "moe" 
+0

這適用於給定的示例名稱,但只是保留第一個單詞。它不適用於像'moe money inc'這樣的字符串。 – Tommy

+0

@湯米 - 公平點,雖然從閱讀OP原始問題和示例,這是他看起來想要的。強大的解決方案應該帶有強大的示例:) +1爲您的答案。 – Chase