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

如何使用cowplot为X轴和Y轴同时添加grob?

问题:如何在ggplot中同时为X轴和Y轴添加图片刻度Grob

我学会了将PNG作为轴刻度标签插入ggplot,但该方法仅适用于单轴,不确定如何为图表同时绘制Y轴和X轴的Grob。

单轴添加Grob的示例代码

library(ggplot2)
library(cowplot)  # 原代码中cowplot2为笔误,正确包名为cowplot
library(png)
library(RCurl)  # 原代码中Rcurl大小写错误,正确包名为RCurl

# 统一数据框命名,避免后续报错
chiMate <- data.frame(
  pairType = c("assortative", "disassortative", "disassortative", "assortative", "disassortative", "disassortative", "assortative"),
  Male_Phenotype = c("metallic", "rufipennis", "metallic", "militaris-a", "metallic", "militaris-a", "rufipennis"),
  Female_Phenotype = c("metallic", "metallic", "militaris-a", "militaris-a", "rufipennis", "rufipennis", "rufipennis"),
  exp = c(0.10204082, 0.11224490, 0.28571429, 0.10204082, 0.02040816, 0.08163265, 0.29591837),
  obs = c(0.04081633, 0.02040816, 0.02040816, 0.03061224, 0.00000000, 0.00000000, 0.03061224)
)

rufiPNG<- "https://i.sstatic.net/Q8BqO.png"
rufipennis <- readPNG(getURLContent(rufiPNG))

militarisPNG<- "https://i.sstatic.net/EtdfR.png"
militaris_a <- readPNG(getURLContent(militarisPNG))

metallicPNG<- "https://i.sstatic.net/YIDoA.png"
metallic <- readPNG(getURLContent(metallicPNG))

# 绘制基础图表
p<- ggplot(chiMate, aes(x = `Male Phenotype`, y = `Female Phenotype`)) +
  geom_point(aes(color = pairType, size = 2.1*exp))+
  geom_point(color = "black", aes(size = 1.6*exp)) +
  geom_point(color = "white", aes(size = 1.3*exp)) +
  geom_point(aes(size = 1.25*obs), color= "salmon") +
  scale_color_manual("Pair type", values = c("assortative" = "cornflowerblue", "disassortative" = "aquamarine3")) +
  scale_size_continuous(range = c(10, 45))+
  scale_x_discrete(expand=c(.3,.3))+
  scale_y_discrete(expand=c(0.3,0.3))+
  geom_text(aes(label= round(obs, digits= 3)))+
  theme_minimal() +
  labs(x = "Male Phenotype", y = "Female Phenotype", size = "Mate Count")+
  theme(legend.position = 'bottom', legend.box.background = element_rect(color='black'),  axis.title = element_text(size= 14), axis.text = element_text(size= 10))+
  guides(color = guide_legend(override.aes = list(size = 12)),  size = "none")

# 创建Y轴图片画布
ystrip <- axis_canvas(p, axis = 'y') + 
  draw_image(rufipennis, y = 2.35, scale = 4) +
  draw_image(militaris_a, y = 1.5, scale = 4) +
  draw_image(metallic, y = .65, scale = 4)

# 仅添加Y轴Grob的效果
ggdraw(insert_yaxis_grob(p, ystrip, position = "left",width = grid::unit(0.05, "null")))

尝试过的无效方法

第一种:

ggdraw(p)+ 
insert_yaxis_grob(p, ystrip, position = "left",width = grid::unit(0.05, "null"))+
insert_xaxis_grob(p, xstrip, position = "bottom",height = grid::unit(0.1, "null"))

第二种:

ggdraw(insert_yaxis_grob(p, ystrip, position = "left",width = grid::unit(0.05, "null")),
insert_xaxis_grob(p, xstrip, position = "bottom",height = grid::unit(0.1, "null")))

解决方案

核心是逐步叠加Grob对象:先基于原始图插入Y轴Grob得到中间图,再基于这个中间图插入X轴Grob,最后用ggdraw()渲染。

完整代码如下:

# 创建X轴图片画布(对应X轴刻度顺序调整坐标)
xstrip <- axis_canvas(p, axis = 'x') + 
  draw_image(metallic, x = 0.3, scale = 4) +  # 对应X轴第一个值metallic
  draw_image(rufipennis, x = 1.3, scale = 4) +  # 对应X轴第二个值rufipennis
  draw_image(militaris_a, x = 2.3, scale = 4)  # 对应X轴第三个值militaris-a

# 第一步:给原始图插入Y轴Grob
p_with_y <- insert_yaxis_grob(p, ystrip, position = "left", width = grid::unit(0.05, "null"))

# 第二步:基于带Y轴Grob的图,插入X轴Grob
p_with_both <- insert_xaxis_grob(p_with_y, xstrip, position = "bottom", height = grid::unit(0.1, "null"))

# 最后渲染完整图表
ggdraw(p_with_both)

失效原因说明

  • 第一种方法中,ggdraw(p)返回的是ggdraw对象,而insert_*_grob返回的是Grob对象,两者无法用+叠加,最终只会保留原始图。
  • 第二种方法中,ggdraw()仅接受第一个参数作为渲染对象,第二个参数会被忽略,因此只有Y轴Grob生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 16:05:54