如果组大多是唯一的,那么如何在dplyr中按组有效地操作?

时间:2018-03-15 05:18:56

标签: r dplyr data.table

我有时间戳数据。有时,很少,由于时间戳的分辨率(例如,到最接近的毫秒),我在单个时间戳获得多个更新。我希望按时间戳分组,聚合数据,然后返回每个组中的最后一行。

我发现在dplyr中要做的显而易见的事情需要很长时间,特别是与data.table相比。虽然这可能部分是由于当组数超过100K时速度data.table多快(参见基准部分here),但我很想知道是否有办法更快地完成此操作在dplyr(或甚至在data.table中),通过利用具有多行的组非常稀疏这一事实。

示例数据(1000万行,只有1000组,数据行超过1行):

tmp_df <- data.frame(grp = seq_len(1e7))
set.seed(0)
tmp_df_dup <- 
    tmp_df %>%
    sample_frac(1e-4) 

tmp_df_dup <-
    tmp_df_dup[rep(seq_len(nrow(tmp_df_dup)), 3), ,drop = F] %>%
    arrange(grp) %>%
    group_by(grp) %>%
    mutate(change = seq(3)) %>%
    ungroup

tmp_df <-
    tmp_df %>%
    left_join(tmp_df_dup, by = 'grp')

以下操作需要7分钟在我的机器上:

time_now <- Sys.time()
tmp_result <-
    tmp_df %>%
    group_by(grp) %>%
    mutate(change = cumsum(change)) %>%
    filter(row_number() == n()) %>%
    ungroup
print(Sys.time() - time_now)
# Time difference of 7.340796 mins

相比之下,data.table只需不到10秒:

time_now <- Sys.time()
setDT(tmp_df)
tmp_result_dt <-
    tmp_df[, .(change = cumsum(change)), by = grp]
tmp_result_dt <-
    tmp_result_dt[tmp_result_dt[, .I[.N], by = grp]$V1]


print(Sys.time() - time_now)

# Time difference of 9.033687 secs

0 个答案:

没有答案