You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用group_by() |> tally()对整数列分箱并显示所有分箱(含空分箱)

解决分箱统计保留空分箱的问题

针对mtcars数据集的hp列按40间隔分箱并保留空分箱的需求,有两种简便方法可以实现:

方法一:用因子强制保留所有分箱水平

先手动生成所有需要的分箱区间,将分箱结果转为因子并指定所有区间为水平,这样统计时空分箱会被保留,最后把NA替换为0即可:

library(dplyr)

# 生成按40间隔的断点,覆盖hp的最小到最大值范围
breaks <- seq(floor(min(mtcars$hp)/40)*40, ceiling(max(mtcars$hp)/40)*40, by = 40)
# 生成分箱标签,格式如"40-80"
labels <- paste0(breaks[-length(breaks)], "-", breaks[-1])

mtcars %>%
  # 按断点分箱,include.lowest确保最小值被包含在第一个分箱
  mutate(hp_bin = cut(hp, breaks = breaks, labels = labels, include.lowest = TRUE)) %>%
  # 强制将分箱转为因子,保留所有预设的分箱水平
  mutate(hp_bin = factor(hp_bin, levels = labels)) %>%
  # 统计每个分箱的数量
  count(hp_bin, name = "count") %>%
  # 把空分箱的NA计数替换为0
  mutate(count = replace(count, is.na(count), 0))

方法二:生成完整分箱表后左连接

先生成包含所有分箱的数据集,再和原数据的统计结果做左连接,空分箱的计数会显示为NA,最后替换为0:

library(dplyr)

breaks <- seq(floor(min(mtcars$hp)/40)*40, ceiling(max(mtcars$hp)/40)*40, by = 40)
labels <- paste0(breaks[-length(breaks)], "-", breaks[-1])

# 生成包含所有分箱的基础表
full_bins <- tibble(hp_bin = labels)

# 统计原数据中各分箱的数量
hp_counts <- mtcars %>%
  mutate(hp_bin = cut(hp, breaks = breaks, labels = labels, include.lowest = TRUE)) %>%
  count(hp_bin, name = "count")

# 左连接后替换空分箱的NA为0
full_bins %>%
  left_join(hp_counts, by = "hp_bin") %>%
  mutate(count = ifelse(is.na(count), 0, count))

原理说明

原来用ggplot2::cut_interval()的方式会丢失空分箱,是因为该函数只会生成数据实际覆盖到的分箱,且group_by() + tally()只会统计存在数据的分组。通过手动生成全部分箱区间并强制保留(因子水平或左连接),就能让空分箱的计数显示为0。

内容的提问来源于stack exchange,提问作者Emman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:11:05