ggplot2:如何将直方图的条与x轴对齐?

ℕʘʘ*_*ḆḽḘ 9 r ggplot2

考虑这个简单的例子

library(ggplot2)
dat <- data.frame(number = c(5, 10, 11 ,12,12,12,13,15,15))
ggplot(dat, aes(x = number)) + geom_histogram()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

看看这些条是如何与x轴奇怪对齐的?为什么栏位于左侧的5.0第一个栏位于10.0中心位置?我怎样才能控制它?例如,对标签右侧的条形图开始更有意义(对我而言).

谢谢!

Sti*_*ibu 17

为什么酒吧"奇怪地对齐"?

让我首先解释一下,为什么你的代码会导致奇怪的对齐条形.这与构建直方图的方式有关.首先,将x轴分成间隔,然后计算每个间隔中的值的数量.

默认情况下,ggplot将数据拆分为30个bin.它甚至吐出一条信息:

stat_bin()使用bins = 30.选择更好的价值binwidth.

默认数量并不总是一个不错的选择.在您的情况下,所有数据点都是整数,人们可能希望选择bin的边界作为5, 6, 7, 8, ...4.5, 5.5, 6.5, ...,这样每个bin只包含一个整数值.您可以获取已在图中使用的箱的边界,如下所示:

data <- data.frame(number = c(5, 10, 11 ,12, 12, 12, 13, 15, 15))
p <- ggplot(data, aes(x = number)) + geom_histogram()
ggplot_build(p)$data[[1]]$xmin
##  [1]  4.655172  5.000000  5.344828  5.689655  6.034483  6.379310  6.724138  7.068966  7.413793
## [10]  7.758621  8.103448  8.448276  8.793103  9.137931  9.482759  9.827586 10.172414 10.517241
## [19] 10.862069 11.206897 11.551724 11.896552 12.241379 12.586207 12.931034 13.275862 13.620690
## [28] 13.965517 14.310345 14.655172
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,不会以导致条形与整数良好对齐的方式选择区间的边界.

因此,简而言之,奇怪对齐的原因是ggplot简单地使用默认数量的30个二进制文件,在您的情况下,不适合使用与整数很好地对齐的条形图.

有(至少)两种方法来获得良好对齐的条形,我将在下面讨论

请改用条形图

由于您有整数数据,因此直方图可能不是可视化的合适选择.您可以改为使用geom_bar(),这将导致以整数为中心的条形:

ggplot(data, aes(x = number)) + geom_bar() + scale_x_continuous(breaks = 1:16)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

您可以通过添加0.5number以下内容将条移动到整数的右侧:

ggplot(data, aes(x = number + 0.5)) + geom_bar() + scale_x_continuous(breaks = 1:16)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

使用适当的箱子创建直方图

如果你想使用直方图,你可以让ggplot使用更合理的bin,如下所示:

ggplot(data, aes(x = number)) +
  geom_histogram(binwidth = 1, boundary = 0, closed = "left") +
  scale_x_continuous(breaks = 1:16)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

使用binwidth = 1,您覆盖默认选择30个bin并明确要求bin应该具有宽度1. boundary = 0确保binning从整数值开始,这是您需要的,如果您希望整数位于左侧的酒吧.(如果省略它,则选择条形图使条形图以整数为中心.)

这个论点closed = "left"有点难以解释.如上所述,现在选择了箱的边界5, 6, 7, ....现在的问题是,例如,6应该是哪个bin?它可以是第一个也可以是第二个.这是由closed以下内容控制的选项:如果将其设置为"right"(默认值),则在右侧关闭分档,这意味着将包含分箱的右边界,而左边界属于分箱剩下.所以,6将在第一个bin中.另一方面,如果您选择"left",左边界将是bin的一部分,6将位于第二个bin中.

由于您希望条形图位于整数的左侧,因此您需要选择closed = "left".

比较两种解决方案

如果将直方图与条形图进行比较,您会发现两个不同之处:

  • 条形图中的条形图之间有一点间隙,而它们在直方图中触摸.您可以通过使用使条形触摸前者geom_bar(width = 1).
  • 对于条形图,最右边的条形在15到16之间,而直方图则在14到15之间.原因是虽然对于所有箱子,只有左边界是箱子的一部分,而对于最右边的箱子,两个边界都包括在内.


tim*_*mat 6

这将使条形图以值为中心

data <- data.frame(number = c(5, 10, 11 ,12,12,12,13,15,15))
ggplot(data,aes(x = number)) + geom_histogram(binwidth = 0.5)
Run Code Online (Sandbox Code Playgroud)

这是一个带有刻度标签的技巧,可以使条形在左侧对齐。但是如果添加其他数据,则还需要移动它们

ggplot(data,aes(x = number)) + 
  geom_histogram(binwidth = 0.5) + 
  scale_x_continuous(
    breaks=seq(0.75,15.75,1), #show x-ticks align on the bar (0.25 before the value, half of the binwidth) 
    labels = 1:16 #change tick label to get the bar x-value
    )
Run Code Online (Sandbox Code Playgroud)

其他选项:(binwidth = 1, breaks=seq(0.5,15.5,1)可能对整数更有意义)