使用数据框中的值将函数应用于向量

时间:2016-03-13 01:11:33

标签: r string lapply gsub sapply

我首先承认我在apply函数中表现得非常糟糕,并且在R中一般都是函数编写。我正在开设一个课程项目来清理和建模一些文本数据,我想包括一个清理收缩的步骤。

qdapDictionaries包中包含一个contractions数据框,其中包含两列,第一列是收缩,第二列是扩展版本。例如:

 contraction  expanded
5  aren't     are not

我想使用这里的值在我的文本上运行gsub函数,我仍然在一个大字符元素中。类似于gsub(contr,expd,text)

这是我用来测试的示例向量:

vct <- c("I've got a problem","it shouldn't be that hard","I'm having trouble 'cause I'm dumb")

我很难理解如何循环数据框(没有实际编写循环,因为它似乎是效率最低的方式)因此我可以运行所有gsub s需要。

这可能是一个简单的答案,但这是我尝试过的:首先,我创建了一个函数,如果通过收缩,它将返回扩展版本:

expand <- function(contr) {
    expd <- contractions[which(contractions[1]==contr),2]
}

我可以使用sapply,它可以或多或少地起作用;在收缩中循环第一列,sapply(contractions[,1],expand)返回带有扩展短语的命名矢量字符。

我无法弄清楚如何将此向量与gsub结合起来。我尝试编写第二个函数gsub_expand并更改expand函数以返回收缩和扩展:

gsub_expand <- function(list, text) {
     text <- gsub(list[[1]],list[[2]],text)
     return(text)
 }

当我跑gsub_expand(sapply(contractions[,1],expand),vct)时,它只纠正了我的一部分矢量。

[1] "I've got a problem"   "it shouldn't be that hard"   "I'm having trouble because I'm dumb"

收缩数据框中的第一个条目是因为因为内部sapply似乎实际上没有循环。我陷入了我想要传递给什么的逻辑,以及我应该绕过的东西。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

两个选项:

stringr::str_replace_all

stringr包与基本正则表达式函数大致相同,但有时候会以极其简单的方式执行。这是其中一次。您可以传递str_replace_all命名列表或字符向量,它将使用名称作为模式,将值用作替换,因此您只需要

library(stringr)
contractions <- c("I've" = 'I have', "shouldn't" = 'should not', "I'm" = 'I am')
str_replace_all(vct, contractions)

你得到了

[1] "I have got a problem"                 "it should not be that hard"          
[3] "I am having trouble 'cause I am dumb"

没有麻烦,没有大惊小怪,只是工作。

lapply / mapply / Mapgsub

您当然可以使用lapplyfor循环来重复gsub。您可以通过几种方式制定此调用,具体取决于数据的存储方式以及您希望如何获取数据。让我们先复制vct,因为我们要覆盖它:

vct2 <- vct

现在我们可以使用以下三种中的任何一种:

lapply(1:length(contractions), 
       function(x){vct2 <<- gsub(names(contractions[x]), contractions[x], vct2)})

# `mapply` is a multivariate version of `sapply`
mapply(function(x, y){vct2 <<- gsub(x, y, vct2)}, names(contractions), contractions)

# `Map` is a multivariate version of `lapply`
Map(function(x, y){vct2 <<- gsub(x, y, vct2)}, names(contractions), contractions)

每个都会返回略有不同的无用数据,但也会将更改保存到vct2,现在看起来与上面str_replace_all的结果相同。

这些有点复杂,主要是因为您需要在每次更改时保存vct的内部版本。 vct <<-写入函数环境外的初始化vct2 ,允许我们捕获连续的更改。对<<-要小心一点;它很强大。有关详细信息,请参阅?assignOps