【问题标题】:How to vectorize a function with multiple possible outputs in an R dataframe如何在 R 数据框中矢量化具有多个可能输出的函数
【发布时间】:2021-12-07 14:20:44
【问题描述】:

我正在尝试将一个函数应用于 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))

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

感谢任何帮助!

【问题讨论】:

    标签: r function dplyr vectorization stringr


    【解决方案1】:

    使用矢量化的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
    

    【讨论】:

    • 完美。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多