group_by 过滤任何命令时速度慢
group_by slow when filtering any command
如果我想 group_by
和 filter
那些在数据集中具有任何 NA
或 factor
值的数据,我想在其中使用 any
函数dplyr
但发现 运行 对于 NAs
或 factor
很慢(但不是为了找到任何数值)。示例数据:
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"的解释在这里如果你有兴趣:
如果您对排序级别不感兴趣,通常首选使用字符而不是分类变量的因子,这样效率更高。
如果我想 group_by
和 filter
那些在数据集中具有任何 NA
或 factor
值的数据,我想在其中使用 any
函数dplyr
但发现 运行 对于 NAs
或 factor
很慢(但不是为了找到任何数值)。示例数据:
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"的解释在这里如果你有兴趣:
如果您对排序级别不感兴趣,通常首选使用字符而不是分类变量的因子,这样效率更高。