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

如何在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,由工具自动处理对齐:

  1. 安装并加载gridExtra包
  2. 修改图像组合与导出代码:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 19:50:34