首页 > 解决方案 > dplyr:按组汇总(总和)非常慢

问题描述

我有两个数据集:(inds个人)和hhs(家庭)。

我正在尝试对所有inds$income按(唯一 ID)分组的内容求和,并在家庭中所有个人的收入总和UID上创建一个新列。hhs有些人没有任何收入,在这种情况下,他们对该变量有“NA”。我正在使用的代码是:

hhs <- left_join(hhs, inds %>% group_by(UID) %>% summarize(hhincome = sum(income, na.rm=TRUE)))

但是,它非常缓慢。inds有超过 200 万行,hhs大约有 550k 行。我曾经dplyr对相同数据集中的相似变量进行平均或计数,通常需要十秒钟或更短的时间才能完成这项工作。有什么我做错了吗?有没有办法让它更快?

编辑:正如我所说,我已经习惯于dplyer获得平均家庭价值而没有问题

hhs <- left_join(hhs, inds %>% filter(AGE > 2) %>% group_by(UID) %>% summarize(L_Bilingual = mean(Bilingual, na.rm=TRUE)))

使用上面的代码计算均值需要 5 秒。该功能是否有什么sum()特别之处使其变慢?

标签: rdplyr

解决方案


使用下面的假数据,在我的机器上汇总和连接大约需要 2 秒,这是一台新的 Macbook Pro。即使使用较慢的机器,它也不会花费超过 10 或 15 秒的时间。连接创建的行是否可能比您想象的多得多?如果您提供有关数据结构的更多详细信息,我们可以更具体地说明可能出现的问题。

library(tidyverse)
library(microbenchmark)

# Generate two data frames with only the UID column in common
set.seed(2)
hhs = data.frame(UID=1:550000, replicate(30, runif(550000))) %>% 
  set_names(c("UID", paste0("V",1:30)))
inds = data.frame(UID=sample(1:550000, 2e6, replace=TRUE), 
                  income=rnorm(2e6, 5e4, 1e4),
                  replicate(20, rnorm(2e6, 5e4, 1e4)))

microbenchmark(join=left_join(hhs, inds %>% group_by(UID) %>% 
                                summarize(hhincome = sum(income, na.rm=TRUE))),
               times=5)
Unit: seconds
 expr      min       lq     mean median       uq      max neval
 join 1.924749 1.988773 2.722018 2.0063 2.068044 5.622223     5

推荐阅读