【问题标题】:Is there a more efficient way to obtain variance of lot's of columns than dplyr?有没有比 dplyr 更有效的方法来获得列的批次差异?
【发布时间】:2021-12-13 05:57:06
【问题描述】:

我有一个超过 250,000 列和 200 行的 data.frame,因此大约有 5000 万个单独的值。我正在尝试对列的方差进行细分,以便选择方差最大的列。

我使用 dplyr 如下:

df %>% summarise_if(is.numeric, var)

它已经在我的 16gb 内存的 imac 上运行了大约 8 个小时。

有没有办法为调用分配更多资源,或者更有效的方法来汇总列之间的差异?

【问题讨论】:

  • 8 小时似乎太多了,即使对于 dplyr 也是如此。听起来有些不对劲。
  • 是的,这很奇怪,正如您在下面看到的那样,转换为长格式大约需要 20 秒...

标签: r dplyr tidyverse summarize


【解决方案1】:

我敢打赌,先选择列,然后计算方差,会快很多:

df <- as.data.frame(matrix(runif(5e7), nrow = 200, ncol = 250000))

df_subset <- df[,sapply(df, is.numeric)]
sapply(df_subset, var)

上面的代码在我的机器上运行大约一秒钟,这是计算每一列的方差,因为在我的示例中它们都是数字。

【讨论】:

  • 谢谢,代码:df_subset
  • 我很惊讶当你运行它时得到的结果。 sapply 确实返回了一个逻辑向量,但随后在 [ 调用中使用它,因此 应该 返回的是 sapply 返回 TRUE 的列的子集。它也适用于我的笔记本电脑,所以我不确定会有什么不同。
【解决方案2】:

您可以尝试使用data.table,这通常更快。

library(data.table)

cols <- names(Filter(is.numeric, df))
setDT(df)
df[, lapply(.SD, var), .SDcols = cols]

您可以尝试的另一种方法是获取长格式数据。

library(dplyr)
library(tidyr)

df %>%
  select(where(is.numeric)) %>%
  pivot_longer(cols = everything()) %>%
  group_by(name) %>%
  summarise(var_value = var(value))

但我同意@Daniel V 的观点,即值得检查数据,因为执行此计算的时间太长了 8 小时。

【讨论】:

  • dplyr 版本在 20 秒内运行。我从没想过宽格式会比长格式花费更长的时间......
【解决方案3】:

非常宽的 data.frames 效率很低。我认为转换为矩阵并使用matrixStats::colVars() 会是最快的。

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多