dplyr 0.8.0中group_by配合cumsum时分组失效问题
解决dplyr 0.8.0中分组后cumsum忽略分组规则的问题
嘿,这个坑我之前踩过!在dplyr 0.8.0版本里,分组后用cumsum()得不到预期的组内累计结果,大概率是因为操作顺序的问题——这个版本的arrange()默认会忽略分组上下文,要是顺序没搞对,很容易让后续的分组计算“跑偏”。
先给你重现一下问题场景(补全你没写完的代码):
library(dplyr) set.seed(123) # 固定随机种子,方便复现 test_data <- data.frame( cat = sample(c("a", "b", "c"), size = 1000, replace = TRUE), date = sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 1000, replace=TRUE) ) %>% mutate(x = 1) %>% arrange(date) %>% # 先全局按日期排序 group_by(cat) %>% # 按cat分组 mutate(cumulative_x = cumsum(x)) # 这里在0.8.0里可能会得到全局累计,而非组内累计
两种靠谱的解决办法:
办法一:先分组,再组内排序
这是最稳妥的操作顺序,因为group_by()之后调用arrange()时,加上.by_group = TRUE参数,就能确保是在每组内部按日期排序,后续的cumsum()自然会严格按组计算:
set.seed(123) fixed_data <- data.frame( cat = sample(c("a", "b", "c"), size = 1000, replace = TRUE), date = sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 1000, replace=TRUE) ) %>% mutate(x = 1) %>% group_by(cat) %>% # 先按cat分组 arrange(date, .by_group = TRUE) %>% # 组内按日期排序 mutate(cumulative_x = cumsum(x)) # 现在每组的cumulative_x是独立累计的 # 验证一下,比如看cat="a"的前几条数据,累计值是按日期递增的组内累计 fixed_data %>% filter(cat == "a") %>% head(10)
办法二:先全局排序,再强制确认分组(适合必须先排序的场景)
如果你因为业务需求必须先做全局排序,那可以在group_by()里明确强化分组上下文,确保后续的cumsum()能识别分组规则:
set.seed(123) fixed_data_alt <- data.frame( cat = sample(c("a", "b", "c"), size = 1000, replace = TRUE), date = sample(seq(as.Date('1999/01/01'), as.Date('2000/01/01'), by="day"), 1000, replace=TRUE) ) %>% mutate(x = 1) %>% arrange(date) %>% group_by(cat, .add = FALSE) %>% # 明确创建新的分组上下文 mutate(cumulative_x = cumsum(x))
本质上,dplyr 0.8.0对arrange()和group_by()的交互逻辑做了调整,默认不再保留分组排序,所以只要把分组放在排序前面,或者明确指定组内排序,就能解决这个问题。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

