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

Using values from a dataframe to apply a function to a vector

首先我要承认我在 R 中的 apply 函数和一般的函数编写方面很糟糕。我正在研究一个课程项目来清理和建模一些文本数据,我想包括一个清理宫缩的步骤。

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是我需要的。

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

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

我可以将 sapply 与此一起使用,它或多或少确实有效;在收缩的第一列上循环,sapply(contractions[,1],expand) return 是一个命名的字符向量,带有扩展的短语。

虽然我不知道如何将这个向量与 gsub 结合起来。我尝试编写第二个函数 gsub_expand 并将扩展函数更改为 return 收缩和扩展:

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"

contractions 数据框中的第一个条目是 'cause 和 because,所以内部 sapply 似乎实际上并没有循环。我被困在我想传递给什么以及我应该循环什么的逻辑中。

感谢您的帮助。

两个选项:


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)

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

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