You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot2中自定义圆矩组合点形状并支持angle参数

实现ggplot2自定义圆形+矩形组合形状(支持角度旋转)

要实现可像geom_point()一样调用的自定义形状,我们可以通过自定义grob组合 + 扩展ggplot2的Geom层来实现,同时支持angle参数的映射。以下是完整实现步骤:

1. 定义生成组合形状的grob函数

用grid包的基础grob组合圆形和矩形,通过rotateGrob实现角度旋转:

library(grid)
library(ggplot2)

circle_rect_grob <- function(x, y, size = 1, angle = 0, 
                             colour = "black", fill = NA, alpha = 1, 
                             stroke = 0.5) {
  # 转换形状尺寸为grid单位
  size_unit <- unit(size, "char")
  
  # 创建圆形grob
  circle <- circleGrob(
    x = x, y = y, r = size_unit / 2,
    gp = gpar(
      col = alpha(colour, alpha),
      fill = alpha(fill, alpha),
      lwd = stroke
    )
  )
  
  # 创建矩形grob(尺寸为圆形直径的2/3,中心对齐)
  rect_width <- size_unit * 2/3
  rect_height <- size_unit * 1/3
  rect <- rectGrob(
    x = x, y = y, width = rect_width, height = rect_height,
    gp = gpar(
      col = alpha(colour, alpha),
      fill = alpha(fill, alpha),
      lwd = stroke
    )
  )
  
  # 围绕中心旋转矩形
  rotated_rect <- rotateGrob(rect, angle = angle, x = x, y = y)
  
  # 组合两个grob
  gTree(children = gList(circle, rotated_rect))
}

2. 创建自定义Geom层

继承GeomPoint,重写draw_panel方法调用自定义grob,并添加angle到美学映射:

GeomCircleRect <- ggproto(
  "GeomCircleRect", GeomPoint,
  # 新增angle到支持的美学参数
  aes_params = c(GeomPoint$aes_params, "angle"),
  
  draw_panel = function(data, panel_params, coord, na.rm = FALSE) {
    # 转换坐标系统
    coords <- coord$transform(data, panel_params)
    
    # 生成组合形状grob
    circle_rect_grob(
      x = coords$x, y = coords$y,
      size = coords$size, angle = coords$angle,
      colour = coords$colour, fill = coords$fill,
      alpha = coords$alpha, stroke = coords$stroke
    )
  },
  
  # 设置默认参数
  default_aes = aes(
    shape = 19, colour = "black", size = 2, fill = NA,
    alpha = 1, stroke = 0.5, angle = 0
  )
)

3. 创建便捷调用函数

封装成和geom_point()用法一致的函数:

geom_circle_rect <- function(mapping = NULL, data = NULL, stat = "identity",
                             position = "identity", na.rm = FALSE, show.legend = NA,
                             inherit.aes = TRUE, ...) {
  layer(
    geom = GeomCircleRect, mapping = mapping, data = data, stat = stat,
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}

4. 使用示例

现在可以像调用geom_point()一样使用,还能映射angle参数:

# 基础使用
ggplot(mtcars, aes(wt, mpg)) +
  geom_circle_rect(fill = "red", colour = "black", size = 3, angle = 45)

# 映射angle参数到数据变量
ggplot(mtcars, aes(wt, mpg, angle = hp, size = disp, fill = cyl)) +
  geom_circle_rect(colour = "black") +
  scale_fill_viridis_c() +
  theme_minimal()

关键说明

  • 形状调整:若要修改矩形与圆形的相对大小/位置,直接调整circle_rect_grob里的rect_width、rect_height参数即可
  • 旋转逻辑:rotateGrob以形状中心为旋转点,确保旋转时整体形状保持居中
  • 参数兼容:完全继承geom_point()的所有参数,新增angle支持数值或变量映射

内容的提问来源于stack exchange,提问作者Bruno Mioto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:28:31