如何在R ggplot2中导出比例匹配的热图与树状图
问题
使用ggplot2+ggdendro绘制水獭下颌骨数据的热图与树状图,按教程代码运行后,调用jpeg导出高分辨率图像时,树状图与热图的纵向排列无法匹配(样本顺序错位)。
导出图像的代码片段:
jpeg(file="HeatDendoTest02.jpeg", units="mm", width=775, height=638, res=300) grid.newpage() print(heatmap_plot, vp = viewport(x = 0.4, y = 0.5, width = 0.8, height = 1.0)) print(dendro_plot, vp = viewport(x = 0.90, y = 0.43, width = 0.2, height = 0.92)) dev.off()
完整代码:
# Cluster & heatmap on otter data # Jeff Oliver # jcoliver@email.arizona.edu # 2017-08-15 ################################################################################ # Load dependencies library("ggplot2") library("ggdendro") library("tidyr") library("grid") # Read in data otter <- read.csv(file = "data/otter-mandible-data.csv", stringsAsFactors = TRUE) # Restrict the data to only two species, A. cinerea & L. canadensis two_species <- c("A. cinerea", "L. canadensis") otter <- otter[otter$species %in% two_species, ] # Force re-numbering of the rows after subsetting rownames(otter) <- NULL # Scale each measurement (independently) to have a mean of 0 and variance of 1 otter_scaled <- otter otter_scaled[, c(4:9)] <- scale(otter_scaled[, 4:9]) # Run clustering otter_matrix <- as.matrix(otter_scaled[, -c(1:3)]) rownames(otter_matrix) <- otter_scaled$accession otter_dendro <- as.dendrogram(hclust(d = dist(x = otter_matrix))) # Create dendrogram plot dendro_plot <- ggdendrogram(data = otter_dendro, rotate = TRUE) + theme(axis.text.y = element_text(size = 6)) # Heatmap # Data wrangling otter_long <- pivot_longer(data = otter_scaled, cols = -c(species, museum, accession), names_to = "measurement", values_to = "value") # Extract the order of the tips in the dendrogram otter_order <- order.dendrogram(otter_dendro) # Order the levels according to their position in the cluster otter_long$accession <- factor(x = otter_long$accession, levels = otter_scaled$accession[otter_order], ordered = TRUE) # Create heatmap plot heatmap_plot <- ggplot(data = otter_long, aes(x = measurement, y = accession)) + geom_tile(aes(fill = value)) + scale_fill_gradient2() + theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.ticks.y = element_blank(), legend.position = "top") # All together grid.newpage() print(heatmap_plot, vp = viewport(x = 0.4, y = 0.5, width = 0.8, height = 1.0)) print(dendro_plot, vp = viewport(x = 0.90, y = 0.43, width = 0.2, height = 0.92))
解决方案
原因分析
手动设置viewport的位置和尺寸参数时,高分辨率导出(res=300)的设备缩放规则会破坏RStudio绘图窗口中看似对齐的布局,导致树状图与热图纵向错位。
方法1:用gridExtra自动对齐布局
无需手动调整viewport,由工具自动处理对齐:
- 安装并加载
gridExtra包 - 修改图像组合与导出代码:
library(gridExtra) # 导出高分辨率图像 jpeg(file="HeatDendoTest02.jpeg", units="mm", width=775, height=638, res=300) # 按列布局,热图占8份宽度,树状图占2份 grid.arrange(heatmap_plot, dendro_plot, ncol=2, widths=c(8,2)) dev.off()
方法2:统一y轴范围+精准设置viewport
如果坚持使用viewport,需确保两个图的y轴范围完全一致,再调整位置参数:
# 获取热图的y轴范围 heatmap_y_range <- layer_scales(heatmap_plot)$y$range$range # 给树状图设置相同的y轴范围,移除边距避免错位 dendro_plot <- dendro_plot + scale_y_continuous(limits = heatmap_y_range, expand = c(0,0)) + theme(axis.text.y = element_text(size=6), plot.margin = margin(0,0,0,0)) # 导出时保持两个图纵向中心对齐 jpeg(file="HeatDendoTest02.jpeg", units="mm", width=775, height=638, res=300) grid.newpage() print(heatmap_plot, vp = viewport(x = 0.4, y = 0.5, width = 0.8, height = 1.0)) print(dendro_plot, vp = viewport(x = 0.9, y = 0.5, width = 0.2, height = 1.0)) dev.off()
额外注意事项
- 确保热图中
accession因子的顺序与树状图的order.dendrogram结果完全一致(你的代码已正确实现) - 导出时避免手动调整
y参数,保持两个图纵向中心对齐(y=0.5)
内容的提问来源于stack exchange,提问作者Debajyoti Kabiraj
相关产品推荐
相关产品推荐

