如何扩展ggplot2的Geom实现坐标轴无内边距的默认效果?
自定义ggplot2 Geom实现无内边距的坐标轴范围适配
首先得澄清一个关键点:geom本身并不负责控制坐标轴的范围,这个工作是由坐标系统(coord)或者刻度(scale)来处理的。你之前尝试修改panel_params里的范围值没用,是因为panel_params是坐标系统计算后的绘图区域参数,改它只会调整点的绘制位置,但坐标轴的刻度、标签是由scale生成的,不会同步更新,所以才会出现绘图区域和坐标轴不匹配的情况。
那要实现「调用自定义geom时,默认让坐标轴精确匹配数据的min(x)到max(x)、min(y)到max(y),无内边距」的需求,不需要修改GeomSimplePoint这个ggproto对象,只需要调整外层的geom_simple_point函数,让它默认带上无内边距的坐标系统配置即可。
修改后的完整代码
# 原GeomSimplePoint的ggproto部分完全不需要改动 GeomSimplePoint <- ggproto("GeomSimplePoint", Geom, required_aes = c("x", "y"), default_aes = aes(shape = 19, colour = "black"), draw_key = draw_key_point, draw_panel = function(data, panel_params, coord) { coords <- coord$transform(data, panel_params) grid::pointsGrob( coords$x, coords$y, pch = coords$shape, gp = grid::gpar(col = coords$colour) ) } ) # 修改geom_simple_point函数,默认添加无内边距的坐标系统 geom_simple_point <- function(mapping = NULL, data = NULL, stat = "identity", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, coord = coord_cartesian(expand = FALSE), ...) { # 返回一个包含图层和坐标系统的列表,这样调用时会自动应用坐标配置 list( layer( geom = GeomSimplePoint, mapping = mapping, data = data, stat = stat, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ), coord ) } # 测试效果 ggplot(mpg, aes(displ, hwy)) + geom_simple_point()
原理说明
coord_cartesian(expand = FALSE)是ggplot2中专门用来控制坐标轴是否扩展(即内边距)的参数,设置为FALSE后,坐标轴会严格匹配数据的最大、最小值,不会额外留出空白。- 我们在
geom_simple_point函数中把coord参数的默认值设为这个配置,同时允许用户传入自定义的coord(比如coord_flip(expand = FALSE)),兼顾了默认行为和灵活性。 - 返回列表的方式可以让geom函数同时输出图层和坐标系统,用户调用时不需要手动加
+ coord_cartesian(expand=FALSE),完全符合你想要的「默认行为」。
如果你不想通过返回列表的方式,也可以在函数内部提示用户添加坐标系统,但显然上面的方式更贴合你的需求——让geom自带这个默认特性。
内容的提问来源于stack exchange,提问作者Giora Simchoni
相关产品推荐
相关产品推荐

