如何恢复dplyr中grouped summarize的旧行为?
我有6个领域的数据,每个领域包含2至6个指标,总计25个指标。42个网络各对应一套领域内的指标。我想要对每个网络下各领域内的指标执行summarize汇总,使用group_by(network_id, domain)后,期望每个网络得到6条结果,但当前结果与原数据结构一致,每个网络仍有25条结果。
使用的代码如下:
testing <- all.meas.qs.2 %>% group_by(network_id, domain) %>% reframe(emerging.pct=sum(emerging)/construct.num, achieving.pct=sum(achieving)/construct.num)
我不得不使用reframe()替代summarize(),因为原代码使用summarize()时被提示每组返回行数不为1,而我认为旧版summarize()的行为应该是每组仅返回1行(每个网络6行)且不会报错。报错信息如下:
Returning more (or less) than 1 row per `summarise()` group was deprecated in dplyr 1.1.0. i Please use `reframe()` instead.
我目前通过重新分组并使用slice(1)保留每组1行来解决,但不确定此方法是否可行。dplyr 1.1.0版本后规则发生了变化,请问如何恢复旧版summarize()的行为?
核心原因
出现这个问题的本质是你在汇总时使用的construct.num是长度大于1的向量,导致sum(emerging)/construct.num返回的不是单个值,而是和construct.num长度一致的结果。旧版dplyr会自动重复这个结果来填充整组行,而1.1.0版本后summarize()强制要求每个汇总表达式返回单个值,否则就会触发报错并引导使用reframe()。
正确的处理方式
要达到旧版summarize()每组返回1行的效果,只需确保汇总表达式返回单个值即可。假设每个network_id + domain组内的construct.num是固定值(比如对应领域的指标总数),可以用以下方式修改代码:
testing <- all.meas.qs.2 %>% group_by(network_id, domain) %>% summarize( emerging.pct = sum(emerging)/first(construct.num), # 取组内第一个construct.num值 achieving.pct = sum(achieving)/first(construct.num), .groups = "drop" # 可选,执行后取消分组,避免后续操作受分组影响 )
如果construct.num在组内有重复但值一致,也可以用unique(construct.num)或mean(construct.num)替代first(),只要能得到组内的单个固定值即可。这样修改后,summarize()会正常返回每组1行的结果,每个网络对应6条数据,符合你的预期。
关于临时解决方法的可行性
你用slice(1)保留每组1行的方法,在construct.num组内值完全一致的情况下是可行的,但如果组内construct.num存在不同值,这种方法会丢失数据细节,不是最优解。建议优先采用上面的方式从根源上确保汇总表达式返回单个值。
能否恢复旧版summarize()行为
dplyr 1.1.0之后没有提供直接恢复旧版summarize()行为的开关,因为官方已经明确将“返回多行”的功能转移到reframe()。但通过确保每个汇总表达式返回单个值,就能实现旧版summarize()每组1行的核心效果。
内容的提问来源于stack exchange,提问作者Stuart

