如何使用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
相关产品推荐
相关产品推荐

