让我先解释一下,为什么您的代码会导致柱子奇怪地对齐。这与直方图的构建方式有关。首先,将x轴分成间隔,然后计算每个间隔中的值的数量。
默认情况下,ggplot
将数据分成30个bin。它甚至输出了一个消息,指出如此:
stat_bin()
使用bins = 30
。使用binwidth
选择更好的值。
默认值并不总是一个好选择。在您的情况下,所有数据点都是整数,可能希望选择边界为5、6、7、8...
或4.5、5.5、6.5...
的bin,以便每个bin都包含一个整数值。您可以按如下方式获取绘图中使用的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
正如你所看到的,这些柱子的边界没有选择一种方式,可以使柱子与整数对齐。
简而言之,造成奇怪对齐的原因是,ggplot
简单地使用了默认的30个柱子,这并不适合您的情况,无法使柱子与整数对齐。
至少有两种方法可以获得漂亮的对齐柱子,我将在下面讨论。
由于您拥有整数数据,直方图可能不是适当的可视化选择。您可以改用 geom_bar()
,这将导致柱子居中于整数:
ggplot(data, aes(x = number)) + geom_bar() + scale_x_continuous(breaks = 1:16)
如果你想将条形图放在整数右侧,只需在number
中加上0.5
:
ggplot(data, aes(x = number + 0.5)) + geom_bar() + scale_x_continuous(breaks = 1:16)
如果您仍然想使用直方图,可以通过以下方式使ggplot使用更合理的区间:
ggplot(data, aes(x = number)) +
geom_histogram(binwidth = 1, boundary = 0, closed = "left") +
scale_x_continuous(breaks = 1:16)
使用binwidth = 1
可以覆盖默认选择的30个条形,并明确要求条形宽度为1。 boundary = 0
确保分箱从整数值开始,如果希望整数在条形左侧,则需要这样做。(如果省略它,则会选择条形居中于整数上)。
参数closed = "left"
有点棘手。如上所述,现在选择箱子的边界是5, 6, 7, ...
。现在的问题是,例如6应该在哪个箱子里?它可能是第一个也可能是第二个。这是由closed
控制的选择:如果将其设置为"right"
(默认值),则箱子在右侧关闭,这意味着箱子的右边界将被包含,而左边界属于左边的箱子。因此,6将在第一个箱子中。另一方面,如果选择了"left"
,则左边界将成为箱子的一部分,6将在第二个箱子中。
由于希望条形在整数左侧,因此需要选择closed = "left"
。
如果比较直方图和条形图,您将注意到两个差异:
geom_bar(width = 1)
使条之间相邻。这将使条形图在数值上居中显示
data <- data.frame(number = c(5, 10, 11 ,12,12,12,13,15,15))
ggplot(data,aes(x = number)) + geom_histogram(binwidth = 0.5)
这里有一个技巧,可以使用刻度标签将柱状图对齐到左侧。 但如果添加其他数据,需要将它们一起移动。
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
)
其他选项:binwidth = 1, breaks=seq(0.5,15.5,1)
(适用于整数可能更有意义)
除了@Stibu的好答案之外,需要注意的是自ggplot2 3.4.0
以来,geom_col
和geom_bar
现在可以使用新的just
参数将条形/柱形图放置在x轴的左侧或右侧。0.5
(默认值)将把列放在中心位置,0
在右侧,1
在左侧:
library(patchwork)
library(ggplot2)
plot1 <- ggplot(dat, aes(x = number)) +
geom_bar(just = 0) +
labs(title = "with just = 0") +
scale_x_continuous(breaks = 1:16)
plot2 <- ggplot(dat, aes(x = number)) +
geom_bar(just = 1) +
labs(title = "with just = 1") +
scale_x_continuous(breaks = 1:16)
plot1 + plot2
library(ggplot2)
dat <- data.frame(number = c(5, 10, 11 ,12,12,12,13,15,15))
#I have added bins=10 to control too many bins, by default it takes 30
#then it is difficult to read the labels
p1 <- ggplot(dat, aes(x = number)) + geom_histogram(bins = 10, color="black")
#use ggplot_build to get access to bin details, subsetting to [5] is used to
#get max of each bin, you can use 3 to get centre, 4 to get left edge etc
#to see all the coponent of this chart, you can just run
#ggplot_build(p1)$data[[1]]
binDetails <- round(ggplot_build(p1)$data[[1]][5], digits = 3)
Scalexx <- scale_x_continuous(breaks = binDetails$xmax)
#final chart
p1+Scalexx
请访问下方链接,观看视频并且如果有帮助的话,请点赞: https://www.youtube.com/watch?v=Za8bTDvmPLk
通过使用这种方法,我们不需要手动计算存储箱的详细信息。如有任何问题,请留言。
这对我有用
+ scale_x_continuous(limits = c(0, NA))
从?scale_x_continuous
,limits
是:
其中之一:
NULL表示使用默认比例范围
长度为两个的数字向量,提供比例的限制。使用NA来引用现有的最小值或最大值
接受现有(自动)限制并返回新限制的函数。请注意,在位置比例上设置限制将删除超出限制范围的数据。如果目的是缩放,请在坐标系中使用limit参数(参见coord_cartesian())。
data_frame
?这是从哪里来的? - Sotosgeom_bar
,则不会出现此行为,这可能是由于直方图引起的。 - Hardik Guptalibrary(tidyverse)
让我补充一下 - ℕʘʘḆḽḘggplot(data, aes(x = number)) + geom_histogram(boundary = 0)
中,直方图的中心会落在 5 和 15 上,但同时也会导致 10 的直方条不在中心位置上。 - nrussell