2011-07-18 51 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