dplyr group_by后summarise保留多余列、行数异常问题咨询
根本原因
问题出在pedestrian不是普通数据框,是tsibble包定义的时间序列专用数据结构(tsibble对象),它自带两类强制绑定的结构属性:
- 时间索引(index):这个数据集的索引列就是你看到被莫名保留的
Date_Time,是tsibble识别时间序列的核心字段 - 序列键(key):这个数据集的键是
Sensor列,用来区分不同路口的行人监测点序列
当你直接对tsibble对象调用dplyr的group_by()时,tsibble会默认把原有时间索引、序列键作为隐式分组变量加入分组规则,不管你有没有把这些列写在group_by()的参数里。你代码里显式指定的分组字段只有month_year,但实际执行聚合时的分组粒度是Date_Time + Sensor + month_year,本质是逐行逐监测点求和,自然返回的行数和原数据接近,也会保留作为隐式分组依据的Date_Time列。
你手动删除Date_Time列后,tsibble丢失了必须的时间索引字段,会被自动降级为普通tibble对象,隐式分组规则同步失效,所以summarise()会按照你显式指定的month_year字段聚合,得到预期的24行结果。
规避方案
不需要手动删列,根据你后续的分析需求选任意一种即可:
- 如果后续不需要做时间序列专属操作,聚合前先转成普通tibble,彻底规避tsibble隐式属性的影响,是最稳妥的写法:
library(tidyverse) library(tsibble) count_all <- pedestrian %>% as_tibble() %>% # 转为普通tibble,丢弃tsibble专属的隐式分组规则 mutate(month_year = format(as.Date(Date), "%Y-%m")) %>% group_by(month_year) %>% summarise(total = sum(Count))
- 如果后续需要保留tsibble结构做时间序列分析,推荐用tsibble自带的时间分组函数
index_by()替代group_by()处理时间维度聚合,原生适配tsibble结构,不会触发隐式分组问题,还能自动生成规范的年月时间类型字段:
count_all <- pedestrian %>% # yearmonth是tsibble提供的年月类型函数,比手动format转字符更适合时间计算 index_by(month_year = yearmonth(Date)) %>% summarise(total = sum(Count))
提示:后续用dplyr操作tsibble、sf这类带自定义结构属性的特殊数据框时,如果出现和预期不符的聚合/连接结果,可以先检查是不是对象自带的隐式分组、属性规则在生效,提前转成普通tibble再操作就能避开大部分这类难排查的问题。
内容的提问来源于stack exchange,提问作者Grimey
相关产品推荐
相关产品推荐

