group_by 过滤任何命令时速度慢

group_by slow when filtering any command

如果我想 group_byfilter 那些在数据集中具有任何 NAfactor 值的数据,我想在其中使用 any 函数dplyr 但发现 运行 对于 NAsfactor 很慢(但不是为了找到任何数值)。示例数据:

library(tidyverse)    
set.seed(10)
    df <- data.frame( group = rep((paste("g", seq(1, 50000, 1), sep = "" )), each =500, length.out = 2500000),
                      binary = rbinom(2500000, 1, 0.5),
                      narow = rep(letters[1:26], each = 2, length.out = 2500000))
    df <- df %>% 
      dplyr::mutate(narow = replace(narow, row_number() == 345 | row_number() == 77777, NA) )

    str(df)
        #'data.frame':  2500000 obs. of  3 variables:
        #$ group : Factor w/ 5000 levels "g1","g10","g100",..: 1 1 1 1 1 1 1 1 1 1 ...
        #$ binary: int  1 0 0 1 0 0 0 0 1 0 ...
        #$ narow : Factor w/ 26 levels "a","b","c","d",..: 1 1 2 2 3 3 4 4 5 5 ...

现在让 group_by 并使用 any binary==1:

提取那些组
system.time(
  dfnew <- df %>% 
    group_by(group) %>% 
    filter(any(binary == 1))
)
# user  system elapsed 
# 0.1     0.0     0.1

这 运行 很快,但是当我做同样的事情来寻找任何 NAs 时,它非常慢(我有一个更大的数据集):

system.time(
  dfnew <- df %>% 
    group_by(group) %>% 
    filter(any(is.na(narow)))
  )
# user  system elapsed 
# 5.25    8.49   13.75 

考虑到之前非常相似的代码很快(1 vs 13.75s),这似乎非常慢。这是可以预料的还是我做错了什么?我想继续使用 any 函数,因为我觉得它很直观。

编辑

它似乎超越了 NAs。如果我 filter any 因子变量,我的响应也很慢:

system.time(
   dfnew <- df %>% 
     group_by(group) %>% 
     filter(any(narow == "a"))
 )
   user  system elapsed 
   5.32    7.45   12.83 

正如@NelsonGon 所提到的,anyNA 是在您的案例中使用的函数。

问题已经在这里提到了:

对于二进制示例,any 将在 binary == 1 第一次出现时得到满足,而 is.na 将遍历整个向量,这里的长度为 2500000

filter(anyNA(narow)) 应该比 filter(any(is.na(narow))

快得多

编辑:实际上 factor 的时间增益非常有限(快 4%)。

但是,将 factor 转换为 character 会使过滤非常快(大约快 100 倍)。 "why"的解释在这里如果你有兴趣:

如果您对排序级别不感兴趣,通常首选使用字符而不是分类变量的因子,这样效率更高。