R中更快的多列部分字符串识别循环

faster multi-column partial string recognition loop in R

我想创建一个快速函数,如果一列中包含的字符串与我的其中一列相同,则 returns 为真或假。 true 或 false 将在单独命名的列中注册。以下是数据结构的示例:

df = data.frame(Authors, A1, A2 [... all the way A63])
# Example of "Authors" column row values: ("A1, A12, A50")
# All other columns equal: NA
# Note: "Authors" has millions of rows.

我有一个嵌套循环,它从通常包含多个这样的 "Authors" / "df[,1]"(示例:"A1, A12, A50")的列中识别作者姓名 "A1",并且returns "True" 到以特定作者 ("A12") 命名的列中,如果作者的姓名包含在此字符串中(或者 "False")。这是一个实现预期结果的缓慢嵌套循环:

for (i in 2:length(df)){
    for (j in 1:nrow(df)) {
df[j,i]= ifelse(grepl(df[j,1],colnames(df[i])), TRUE, FALSE)}}
# Intended result df[2,2] = "True" if df[2,1] = ("A1, A2, A50"), otherwise "False".

上面的方法有效,但速度慢得令人难以忍受。我有数百万行。 关于如何加快速度的任何指示?

编辑:下面是我的数据框通过 dput 的样子:

structure(list(Authurs = c("A. Trevor Thrall", "A. Trevor Thrall", 
"A. Trevor Thrall", "A. Trevor Thrall, Benjamin H. Friedman", 
"A. Trevor Thrall, Benjamin H. Friedman", "A. Trevor Thrall, Benjamin H. Friedman, Christopher A. Preble, Peter Russo", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey"), `Jeffrey A. Singer` = c(NA_character_, 
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, 
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_, 
NA_character_, NA_character_, NA_character_, NA_character_), 
    `Caroline Dorminey` = c(NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_
    ), `Eric Gomez` = c(NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_
    ), `John Samples` = c(NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_
    ), `Emma Ashford` = c(NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_, NA_character_, NA_character_, NA_character_
    )), row.names = c(NA, 15L), class = "data.frame")

我修改了您的对象片段,使其具有一些实际点击率。

df <- 
structure(list(Authors = c("A. Trevor Thrall", "A. Trevor Thrall", 
"A. Trevor Thrall", "A. Trevor Thrall, Benjamin H. Friedman", 
"A. Trevor Thrall, Benjamin H. Friedman", "A. Trevor Thrall, Benjamin H. Friedman, Christopher A. Preble, Peter Russo", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey", "A. Trevor Thrall, Caroline Dorminey", 
"A. Trevor Thrall, Caroline Dorminey"), `A. Trevor Thrall` = c(TRUE, 
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 
TRUE, TRUE, TRUE), `Benjamin H. Friedman` = c(FALSE, FALSE, FALSE, 
TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE), `Christopher A. Preble` = c(FALSE, FALSE, FALSE, 
FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE), `Peter Russo` = c(FALSE, FALSE, FALSE, 
FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE), `Caroline Dorminey` = c(FALSE, FALSE, FALSE, 
FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 
TRUE, TRUE)), row.names = c(NA, 15L), class = "data.frame")

既然有一些点击,试试这个:

df[-1] <- lapply(names(df[-1]), function(nm) grepl(nm, df[[1]]))

它遍历每个非"Authors" 列名称并根据'Authors' 列中是否有grepl-hit 设置TRUE 或FALSE。我认为这就是您所要求的,我向您保证,它将比使用 ifelse 测试的双嵌套循环快得多。我删除的是内部循环,并用矢量化操作代替它。外层循环基本上没有变化,因为 lapplysapply 在速度方面实际上都等同于 for 循环。重要的是循环内的算法。