我有一个大数据集(df)〜250.000个观察值,其中包括一列cleanText(其中包含以任何数字,标点,大写字母等形式清除的文本),并且有公司名称列表。我想检查df $ cleanText中与公司名称列表中的公司是否匹配的每个观察值,并计算它找到并存储的匹配数量。我的代码有效,但是,它大约需要20个小时才能执行,而且我觉得它可能要快得多。
到目前为止,我还无法弄清楚什么可行。
# Start for loop for each row in df
for(i in 1:nrow(df)){
# store matches in companyNameMatch, make sure the paste0 includes \\b to match whole strings
companyNameMatch <- sapply(list_Companies, function(x) grepl(paste0(x, "\\b"), as.character(df$cleanText[i])))
# Calculate the number of matches and store it
df$companyNameMatch[i] <- as.numeric(length(which(companyNameMatch != 0)))
}
我希望代码应该能够在几个小时左右的时间内运行。
示例
cleanText <- c("keeping a cool head takes practice nike",
"playing soccer on these adidas",
"just having a laugh",
"nike and adidas perform better than crocs")
list_Companies <- c("nike", "adidas", "crocs", "puma")
对于df $ cleanText中的每一行,sapply函数应检查是否与list_Companies中的一行匹配。在这种情况下,结果看起来是这样的:
df$companyNameMatch[1] = 1
df$companyNameMatch[2] = 1
df$companyNameMatch[3] = 0
df$companyNameMatch[4] = 3
答案 0 :(得分:2)
您可以将sapply
与rowSums
一起使用
df$companyNameMatch <- rowSums(sapply(list_Companies, function(x) grepl(x, cleanText)))
使用microbenchmark
软件包,我们可以明显地提高速度:
Unit: microseconds
expr min lq mean median uq max neval cld
rowSums 65.382 78.496 132.345 93.511 119.55 1462.727 100 a
for_loop 6206.326 6920.394 11170.353 7340.814 10058.53 170440.373 100 b
答案 1 :(得分:1)
使用base R
,我们可以遍历'listCompanies,使用grepl
和Reduce
逻辑向量的list
成为一个
Reduce(`+`, lapply(list_Companies, grepl, cleanText))
#[1] 1 1 0 3
或tidyverse
的类似选项
library(tidyverse)
map(list_Companies, str_detect, string = cleanText) %>%
reduce(`+`)