ggplot2自定义Geom线段图例符号显示异常问题求助
修复自定义ggplot2 geom的图例符号显示问题
背景
我正在R中基于geom_segment()开发ggplot2的自定义geom,代码如下:
geom_custom <- function(mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) { out <- layer( data = data, mapping = mapping, stat = stat, geom = CustomGeom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) out } CustomGeom <- ggproto("CustomGeom", Geom, required_aes = c("x", "y", "xend"), non_missing_aes = c("linetype", "linewidth"), default_aes = aes( colour = "black", linewidth = 2, size = 2, linetype = 1, alpha = NA ), draw_panel = function(data, panel_params, coord, ...) { # Return all components grid::gList( GeomSegment$draw_panel(data, panel_params, coord, ...) ) } )
问题
当前问题是图例符号错误地显示为形状,而非geom_segment()默认的线段。以下是示例可复现代码:
df <- tibble::tribble( ~"record", ~"status", ~"start_time", ~"end_time", 1, "status1", 0, 5, 2, "status1", -2, 7, 3, "status2", 2, 15 ) ggplot() + geom_custom(data = df, mapping = aes(x = start_time, xend = end_time, y = record, colour = status))
当前输出图例为形状,而使用geom_segment()的预期输出图例为线段。
解决方案
问题根源在于自定义的CustomGeom继承自基础Geom类,其默认的图例绘制函数是用于点形状的draw_key_point,而geom_segment()使用的是线段类型的draw_key_path。你可以通过以下两种方式修正:
方法1:让自定义Geom继承自GeomSegment
既然你的自定义geom本质上调用的是GeomSegment的绘制逻辑,直接让CustomGeom继承GeomSegment,就能自动继承正确的图例绘制规则,同时简化代码:
geom_custom <- function(mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE) { out <- layer( data = data, mapping = mapping, stat = stat, geom = CustomGeom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) out } CustomGeom <- ggproto("CustomGeom", GeomSegment, required_aes = c("x", "y", "xend"), # 保留自定义的必填美学映射 non_missing_aes = c("linetype", "linewidth"), default_aes = aes( colour = "black", linewidth = 2, size = 2, linetype = 1, alpha = NA ), draw_panel = function(data, panel_params, coord, ...) { GeomSegment$draw_panel(data, panel_params, coord, ...) } )
方法2:显式指定图例绘制函数
如果需要保持继承自Geom,只需在CustomGeom中添加draw_key = draw_key_path参数,指定用线段绘制图例:
CustomGeom <- ggproto("CustomGeom", Geom, required_aes = c("x", "y", "xend"), non_missing_aes = c("linetype", "linewidth"), default_aes = aes( colour = "black", linewidth = 2, size = 2, linetype = 1, alpha = NA ), draw_key = draw_key_path, # 添加该行指定图例绘制函数 draw_panel = function(data, panel_params, coord, ...) { grid::gList( GeomSegment$draw_panel(data, panel_params, coord, ...) ) } )
两种方法都能让图例显示为geom_segment()默认的线段样式,运行示例代码即可验证效果。
内容的提问来源于stack exchange,提问作者rsh52
相关产品推荐
相关产品推荐

