Base R hist()函数生成直方图频率异常问题咨询
Base R
hist() 生成不对称直方图的原因及解决方法 你的问题核心是Base R的hist()函数默认自动分箱逻辑不保证正负对称数据的分箱对齐,而ggplot2的geom_histogram()在指定binwidth后会采用规则对称的分箱方式,所以两者结果不同。
具体原因
hist()默认会根据数据范围和nclass.Sturges()计算的分箱数自动生成断点,这个过程不会刻意保持正负对称:
- 对于负值数据,断点会基于最小值到0的范围生成;对于正值数据,断点基于0到最大值生成。
- 由于分箱数取整、浮点数精度等细节,正负两组的断点不会严格镜像对称,导致部分数据被划分到不同的箱子中,最终出现频率计数差异。
举个简单例子:假设你的负值范围是-7到-2,hist()自动生成的断点可能是-8, -6, -4, -2, 0;而正值范围2到7的自动断点可能是0, 2, 4, 6, 8。由于hist()默认采用左开右闭(right=TRUE)的箱子规则,负值的-2会被划入(-4,-2],而正值的2会被划入(0,2]——这就导致相同绝对值的数被分到了不同宽度的箱子里,最终计数看起来不一致。
解决方法:手动指定对称断点
要让hist()生成和ggplot一致的对称直方图,只需手动给两组数据指定完全镜像的断点,比如和ggplot中binwidth=5匹配的断点:
# 获取数据的最大绝对值,确保断点覆盖所有数据 max_val <- max(abs(Skew_Data$Neg_ModerateSkew_0.5to1)) # 生成对称的断点序列,步长和ggplot的binwidth一致 breaks <- seq(-max_val - 5, max_val + 5, by = 5) # 绘制负值直方图 hist(Skew_Data$Neg_ModerateSkew_0.5to1, breaks = breaks, col = "lightblue") # 绘制正值直方图 hist(Skew_Data$Pos_ModerateSkew_0.5to1, breaks = breaks, col = "lightgreen")
指定相同的断点后,正负两组数据的分箱规则完全一致,直方图就会呈现预期的对称效果。
为什么ggplot的结果正确?
ggplot2::geom_histogram()在指定binwidth时,默认会将分箱对齐到binwidth的整数倍(比如binwidth=5时,箱子边界为..., -10, -5, 0, 5, 10,...),这种对齐方式天然保证了正负数据的分箱对称,因此两组直方图完全一致。
内容的提问来源于stack exchange,提问作者Jay05
相关产品推荐
相关产品推荐

