我们公司的图表布局基于 Excel。在 Excel 中,默认情况下,y 轴文本和网格线从图表底部开始,到图表顶部结束。使用 R 和 ggplot2,默认行为似乎只显示数据的最小值和最大值之间的标签。
手动,我会像下面的例子一样使用限制来达到预期的结果。但是,有没有办法自动实现这种行为?对每个图表手动执行此操作不是一种选择,因为我们有数百个图表,其中数据随时间变化。
library( ggplot2 )
# transform data to make the problem more obvious
df <- cars
df$speed <- df$speed + 4
# default ggplot behaviour: y-axis grid lines and ticks are placed where they fit best
ggplot( df, aes( x = dist, y = speed ) ) +
geom_line() +
ggtitle( "Default behavior: y-axis grid lines and text inside data-range" ) +
scale_y_continuous( expand = c( 0, 0 ) ) +
theme( panel.background = element_rect( fill = "white" ),
panel.border = element_blank(),
panel.grid.major.y = element_line( colour = "#d9d9d9",
size = 0.001 ),
axis.ticks.x = ggplot2::element_line( color = "#d9d9d9" ),
axis.ticks.y = ggplot2::element_blank() )
# desired outcome: y-axis text and grid lines start at bottom and end at top (achieved with expand and limits)
ggplot( df, aes( x = dist, y = speed ) ) +
geom_line() +
ggtitle( "Disired outcome: y-axis grid lines and text at bottom and top" ) +
scale_y_continuous( expand = c( 0, 0 ),
limits = c( 5, 30 ) ) +
theme( panel.background = element_rect( fill = "white" ),
panel.border = element_blank(),
panel.grid.major.y = element_line( colour = "#d9d9d9",
size = 0.001 ),
axis.ticks.x = ggplot2::element_line( color = "#d9d9d9" ),
axis.ticks.y = ggplot2::element_blank() )
默认的 ggplot2 行为:请注意 y 轴文本和网格线未与图表的底部和顶部对齐
期望的结果:y 轴文本和网格线位于图表的底部和顶部(值 5 和 30)
最佳答案
因为比例尺的 limits
参数可以接受将应用于数据范围的函数,所以我们可以创建一个自动将限制设置为更好数字的函数。这是您可以使用的示例函数,但我没有针对所有可能的情况测试它。
library( ggplot2 )
# transform data to make the problem more obvious
df <- cars
df$speed <- df$speed + 4
nicelimits <- function(x) {
# x is the range of the data
# get breaks under default breaks behaviour (breaks are not known in advance)
breaks <- scales::extended_breaks()(x)
# Take the difference between breaks (should be constant)
width <- diff(breaks)[1]
# Do something like `floor()`, but with `width`-units
start <- (x[1] %/% width) * width
# Do something like `ceiling()`, but with `width`-units
end <- (c(x[2] %/% width) + 1) * width
c(start, end)
}
ggplot( df, aes( x = dist, y = speed ) ) +
geom_line() +
scale_y_continuous( expand = c( 0, 0 ),
limits = nicelimits) +
theme( panel.background = element_rect( fill = "white" ),
panel.border = element_blank(),
panel.grid.major.y = element_line( colour = "#d9d9d9",
size = 0.001 ),
axis.ticks.x = ggplot2::element_line( color = "#d9d9d9" ),
axis.ticks.y = ggplot2::element_blank() )
由 reprex package 创建于 2020-12-20 (v0.3.0)
编辑:正如评论中的@stefan 指出的那样,这也将成为很好的限制并且更少的自定义代码:
nicelimits <- function(x) {
range(scales::extended_breaks(only.loose = TRUE)(x))
}
我注意到的一个区别是,如果上限处于中断状态,第一个函数会将上限扩展 + width
,而在这种情况下,后一个函数将返回自然上限。
关于r - 自动将 y 轴文本和网格线对齐到 ggplot 的底部和顶部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65378370/