在 R 中结合变异和文本搜索
Combining mutate and text search in R
我正在尝试创建新的列来指示给定的单词是否在一个较大的句子中,这样我就可以过滤掉所有在评论部分使用“慢”或“快乐”一词的参与者。
举个简单的例子...
fruit_list = data.frame(c("apple", "bannana", "cherries"))
person <- seq(1:3)
comment <- c("I like apple pie", "The worst flavor is bannana", "Those cherries are cheap")
df <- data.frame(person,comment)
for (i in 1:nrow(fruit_list)){
for (j in 1:nrow(df)){
df[i,j+2] <- (as.integer(grepl(fruit_list[i,], df[j,2], fixed=TRUE)))
}
}
以上代码的工作原理在于它正确地放置了 0 或 1,但是当我将其扩展到更大的要搜索的单词列表(即水果)和更多的句子(即评论)时,它(不足为奇)变得很慢。
我想知道使用 mutate 方法是否会更有效,做这样的事情
df <- df %>%
mutate(
apple = as.integer(grepl(fruit_list[1,], comment, fixed =TRUE))
) %>%
mutate(
bannana = as.integer(grepl(fruit_list[2,], comment, fixed =TRUE))
) %>%
mutate(
cherries = as.integer(grepl(fruit_list[3,], comment, fixed =TRUE))
)
这里唯一的问题是我无法弄清楚如何循环浏览水果列表中的项目,所以我不得不直接对名称进行编码。对于可管理的三个项目,但我希望它扩展到几十个搜索词。我以前使用过简单的 sapply 和 lapply,但我不确定如何在这种更复杂的情况下使用它们。
我打赌有某种方法可以从列表中提取变异列的名称,并使用与 grepl 的搜索词相同的值,但我无法将它们拼凑起来。
如有任何建议,我们将不胜感激 - 即使是与我尝试的方向完全不同的建议。
你可以使用
library(tidyverse)
df %>%
mutate(names = str_extract(comment, fruit_list),
values = 1) %>%
pivot_wider(names_from = names,
values_from = values,
values_fill = 0)
这个returns
# A tibble: 3 x 5
person comment apple bannana cherries
<int> <chr> <dbl> <dbl> <dbl>
1 1 I like apple pie 1 0 0
2 2 The worst flavor is bannana 0 1 0
3 3 Those cherries are cheap 0 0 1
注意: 我将您的 fruit_list
从 data.frame 更改为矢量(为了简化)。在您的示例中,您可以使用 fruit_list[,1]
而不是向量 fruit_list
.
我们可以使用dplyr
和purrr::map_dfc
。使用水果矢量比 data.frame:
更容易
library(purrr)
library(dplyr)
fruits<-c("apple", "bannana", "cherries")
map_dfc(fruits, ~+grepl(.x, comment)) %>%
set_names(fruits) %>%
bind_cols(df, .)
或者只是:
df %>% mutate(set_names(map_dfc(fruits, ~ +grepl(.x, comment)), fruits))
输出
person comment apple bannana cherries
1 1 I like apple pie 1 0 0
2 2 The worst flavor is bannana 0 1 0
3 3 Those cherries are cheap 0 0 1
我正在尝试创建新的列来指示给定的单词是否在一个较大的句子中,这样我就可以过滤掉所有在评论部分使用“慢”或“快乐”一词的参与者。
举个简单的例子...
fruit_list = data.frame(c("apple", "bannana", "cherries"))
person <- seq(1:3)
comment <- c("I like apple pie", "The worst flavor is bannana", "Those cherries are cheap")
df <- data.frame(person,comment)
for (i in 1:nrow(fruit_list)){
for (j in 1:nrow(df)){
df[i,j+2] <- (as.integer(grepl(fruit_list[i,], df[j,2], fixed=TRUE)))
}
}
以上代码的工作原理在于它正确地放置了 0 或 1,但是当我将其扩展到更大的要搜索的单词列表(即水果)和更多的句子(即评论)时,它(不足为奇)变得很慢。
我想知道使用 mutate 方法是否会更有效,做这样的事情
df <- df %>%
mutate(
apple = as.integer(grepl(fruit_list[1,], comment, fixed =TRUE))
) %>%
mutate(
bannana = as.integer(grepl(fruit_list[2,], comment, fixed =TRUE))
) %>%
mutate(
cherries = as.integer(grepl(fruit_list[3,], comment, fixed =TRUE))
)
这里唯一的问题是我无法弄清楚如何循环浏览水果列表中的项目,所以我不得不直接对名称进行编码。对于可管理的三个项目,但我希望它扩展到几十个搜索词。我以前使用过简单的 sapply 和 lapply,但我不确定如何在这种更复杂的情况下使用它们。
我打赌有某种方法可以从列表中提取变异列的名称,并使用与 grepl 的搜索词相同的值,但我无法将它们拼凑起来。
如有任何建议,我们将不胜感激 - 即使是与我尝试的方向完全不同的建议。
你可以使用
library(tidyverse)
df %>%
mutate(names = str_extract(comment, fruit_list),
values = 1) %>%
pivot_wider(names_from = names,
values_from = values,
values_fill = 0)
这个returns
# A tibble: 3 x 5
person comment apple bannana cherries
<int> <chr> <dbl> <dbl> <dbl>
1 1 I like apple pie 1 0 0
2 2 The worst flavor is bannana 0 1 0
3 3 Those cherries are cheap 0 0 1
注意: 我将您的 fruit_list
从 data.frame 更改为矢量(为了简化)。在您的示例中,您可以使用 fruit_list[,1]
而不是向量 fruit_list
.
我们可以使用dplyr
和purrr::map_dfc
。使用水果矢量比 data.frame:
library(purrr)
library(dplyr)
fruits<-c("apple", "bannana", "cherries")
map_dfc(fruits, ~+grepl(.x, comment)) %>%
set_names(fruits) %>%
bind_cols(df, .)
或者只是:
df %>% mutate(set_names(map_dfc(fruits, ~ +grepl(.x, comment)), fruits))
输出
person comment apple bannana cherries
1 1 I like apple pie 1 0 0
2 2 The worst flavor is bannana 0 1 0
3 3 Those cherries are cheap 0 0 1