使用 `dplyr` 查找大 tibble 的 row-wise 均值和方差的最快方法是什么?
What is the fastest way to use `dplyr` to find the row-wise mean and variance of a large tibble?
我希望为数字小标题中的每一行生成均值和方差值。使用我现有的代码,我认为这是一个非常适合 dplyr 的解决方案,需要几个小时才能完成大约 35 列的 50,000 行。
有没有办法只使用 dplyr 来加速这个操作?我知道 apply 和 purrr 是选项,但我最好奇的是,在执行像这样的大量计算时,我是否忽略了 dplyr 的某些内容。
可重现的例子:
library(tidyverse)
library(vroom)
gen_tbl(50000, cols = 40,
col_types = paste0(rep("d", 40), collapse = "")) %>%
rowwise() %>%
mutate(mean = mean(c_across()),
var = var(c_across()))
我怀疑 rowwise()
但我很感兴趣是否有更细微的方法可以用 dplyr 解决这个问题,或者这不是 dplyr 擅长的问题。
行向方法的处理时间似乎呈二次方增长:
旋转时间越长,计算速度大约快 300 倍。对于 50k 行,下面的代码用了 1.2 秒,而 rowwise
方法用了 372 秒。
df %>%
mutate(row = row_number()) %>%
tidyr::pivot_longer(-row) %>%
group_by(row) %>%
summarize(mean = mean(value),
var = var(value)) %>%
bind_cols(df, .)
如果你能得到像 matrixStats::rowVars()
这样的 row-wise 方差函数,你就可以做到这一点。我不确定为什么 c_across()
不这样做,但 across()
似乎有效。我从 this issue
得到的
library(tidyverse)
library(vroom)
gen_tbl(
rows = 50000,
cols = 40,
col_types = paste0(rep("d", 40), collapse = "")
) %>%
mutate(
mean = rowMeans(across(everything())),
# var = rowVars(across(everything())),
.before = everything()
)
# A tibble: 50,000 x 41
# mean X1 X2
# <dbl> <dbl> <dbl>
# 1 0.199 -0.715 -1.64
# 2 -0.212 -0.983 -1.38
# 3 0.126 -0.135 0.263
我希望为数字小标题中的每一行生成均值和方差值。使用我现有的代码,我认为这是一个非常适合 dplyr 的解决方案,需要几个小时才能完成大约 35 列的 50,000 行。
有没有办法只使用 dplyr 来加速这个操作?我知道 apply 和 purrr 是选项,但我最好奇的是,在执行像这样的大量计算时,我是否忽略了 dplyr 的某些内容。
可重现的例子:
library(tidyverse)
library(vroom)
gen_tbl(50000, cols = 40,
col_types = paste0(rep("d", 40), collapse = "")) %>%
rowwise() %>%
mutate(mean = mean(c_across()),
var = var(c_across()))
我怀疑 rowwise()
但我很感兴趣是否有更细微的方法可以用 dplyr 解决这个问题,或者这不是 dplyr 擅长的问题。
行向方法的处理时间似乎呈二次方增长:
旋转时间越长,计算速度大约快 300 倍。对于 50k 行,下面的代码用了 1.2 秒,而 rowwise
方法用了 372 秒。
df %>%
mutate(row = row_number()) %>%
tidyr::pivot_longer(-row) %>%
group_by(row) %>%
summarize(mean = mean(value),
var = var(value)) %>%
bind_cols(df, .)
如果你能得到像 matrixStats::rowVars()
这样的 row-wise 方差函数,你就可以做到这一点。我不确定为什么 c_across()
不这样做,但 across()
似乎有效。我从 this issue
library(tidyverse)
library(vroom)
gen_tbl(
rows = 50000,
cols = 40,
col_types = paste0(rep("d", 40), collapse = "")
) %>%
mutate(
mean = rowMeans(across(everything())),
# var = rowVars(across(everything())),
.before = everything()
)
# A tibble: 50,000 x 41
# mean X1 X2
# <dbl> <dbl> <dbl>
# 1 0.199 -0.715 -1.64
# 2 -0.212 -0.983 -1.38
# 3 0.126 -0.135 0.263