如何在 R 数据帧中向量化具有多个可能输出的函数

How to vectorize a function with multiple possible outputs in an R dataframe

我正在尝试将函数应用于 R 中的 data.frame 列,以检测特定字符串值是否存在。有各种字符串模式,每一种都构成了自己的分类。该函数应创建一个新列,根据 dat$id 列中的字符串提供所述分类 (dat$id_class)。

我依靠 stringrdplyr 包来完成这项工作。具体来说,我正在使用 dplyr::mutate 来应用该功能。

这段代码运行并产生了我正在寻找的准确结果,但我正在寻找一种更快的解决方案(如果存在的话)。这显然是一个数据集有限的小规模示例,而在我非常大的数据集上采用同样的方法所花费的时间比预期的要长得多。

library(stringi)
library(dplyr)
library(stringr)

dat <- data.frame(
            id = c(
                    sprintf("%s%s%s", stri_rand_strings(1000000, 5, '[A-Z]'),
                    stri_rand_strings(5, 4, '[0-9]'), stri_rand_strings(5, 1, '[A-Z]'))
            ))


classify <- function(x){
  if(any(stringr::str_detect(x,pattern = c('AA','BB')))){
    'class_1'
  } else if (any(stringr::str_detect(x,pattern = c('AB','BA')))){
    'class_2'
  } else {
    'class_3'
  }
}

dat <- dat %>% rowwise() %>% mutate(id_class = classify(id))

很有可能这个问题已经得到解答,我只是没有找对地方,但值得一试。

感谢任何帮助!

使用矢量化的 case_when 而不是使用 if/else 执行 rowwise 更改模式 OR (|)

library(stringr)
library(dplyr)
system.time({
 dat1 <- dat %>%
    mutate(id_class = case_when(str_detect(id, 'AA|BB') ~'class_1', 
            str_detect(id, 'AB|BA') ~ 'class_2', TRUE ~ 'class_3'))
})
#  user  system elapsed 
#  0.460   0.036   0.493 

基于OP函数的计时

system.time({dat2 <- dat %>%
               rowwise() %>% 
                mutate(id_class = classify(id))
  })
#  user  system elapsed 
# 31.927   0.303  32.891 

-检查输出

> all.equal(dat1, as.data.frame(dat2), check.attributes = FALSE)
[1] TRUE