【问题标题】:R ggplot heatmap with multiple rows having separate legends on the same graphR ggplot 热图,多行在同一图表上具有单独的图例
【发布时间】:2020-08-19 19:32:04
【问题描述】:

我正在尝试使用 ggplot2 制作一个热图,其中包含 3 种类型的变量,每种类型的变量都需要自己独立的图例/比例。

我可以将它们全部绘制在一张热图中(如下图所示),但我无法将它们分开以拥有自己的图例。我的三个类别是“Score”、“samp1”行和其余数据。我希望它们中的每一个都有自己独立的传说和各自的范围。

我唯一的补充是让行分数有绿色、黄色、红色(低、中、高)配色方案,如果可以包含在这个问题中的话。

这是我用来创建该图表的代码

library(ggplot2)
test_data <- read.csv("test_table.csv", row.names = 1)

ggplot(test_data, aes(x=sample, y=id, fill = value)) + 
  geom_raster() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1), # lables vertical
        strip.text.y = element_blank()) +  #remove facet bar on y 
  scale_fill_gradient(low = "darkblue", high = "lightblue") +
  ggtitle("test table") +
  facet_grid(rows = vars(test_data$category), 
             cols = vars(test_data$group), scales = "free", space="free_y") #facets to add gaps 

我使用分面来按样本和我上面描述的 3 个类别分隔数据。我也希望使用这个分组来创建他们自己的图例,但我不确定这是否可能。

点击here下载数据(预熔)。

提前谢谢你。

【问题讨论】:

  • 我正在考虑的另一种方法是将它们作为 3 个单独的图表,然后尝试将它们组合起来。如果这是要走的路,我也可以提供单独的数据。

标签: r ggplot2 scale legend heatmap


【解决方案1】:

这可以通过ggnewscale 包来实现,如下所示:

library(ggplot2)
library(dplyr)
library(ggnewscale)

ggplot() +
  geom_raster(data = filter(test_data, category == "1 score"), aes(x = sample, y = id, fill = value)) +
  scale_fill_gradient2(low = "green", mid = "yellow", high = "red", midpoint = 4, name = "Score") +
  new_scale_fill() +
  geom_raster(data = filter(test_data, category == "2 samp1"), aes(x = sample, y = id, fill = value)) +
  scale_fill_gradient(low = "darkblue", high = "lightblue", name = "Sample1") +
  new_scale_fill() +
  geom_raster(data = filter(test_data, category == "3 samp2"), aes(x = sample, y = id, fill = value)) +
  scale_fill_gradient(low = "darkblue", high = "lightblue", name = "Sample2") +
  ggtitle("test table") +
  facet_grid(
    rows = vars(category),
    cols = vars(group), scales = "free", space = "free_y"
  ) +
  theme(
    axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1),
    strip.text.y = element_blank()
  )

【讨论】:

  • 谢谢!这正是我一直在寻找的方法。
【解决方案2】:

我会建议下一个方法。按组拆分数据,然后使用函数为每个组构建单独的图。最后使用purrrpatchwork 加入具有不同图例的所有情节。代码如下:

library(purrr)
library(ggplot2)
library(patchwork)
#Load data
test_data <- read.csv("test_table.csv", row.names = 1)
#Split into list
List <- split(test_data,test_data$group)
#Function for plots
myfun <- function(x)
{
  G <- ggplot(x, aes(x=sample, y=id, fill = value)) + 
    geom_raster() + 
    theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1), # lables vertical
          strip.text.y = element_blank()) +  #remove facet bar on y 
    scale_fill_gradient(low = "darkblue", high = "lightblue") +
    facet_grid(rows = vars(x$category), 
               cols = vars(x$group), scales = "free", space="free_y")
  return(G)
}
#Apply
List2 <- lapply(List,myfun)
#Plot
reduce(List2, `+`)+plot_annotation(title = 'My plot')

输出:

您可以进一步了解patchwork 以及如何加入多个情节。

【讨论】:

  • 你可以用patchwork::wrap_plots()代替Reduce
  • 这太棒了,我将不得不为未来的项目记住拼凑。非常感谢您的建议!
【解决方案3】:

当然可以制作 3 个图并将它们粘在一起,但考虑到刻面的形状不同,这并不理想。您可以按照 Stefan 使用 ggnewscale 包,现在它在 CRAN 上更容易,但如果您想在没有附加组件的单个 ggplot 中执行此操作,它可能的。您只需要绘制一个由大实心方块组成的geom_point。这允许您使用颜色比例以及填充比例。

ggplot(test_data, aes(x=sample, y=id, fill = value)) + 
  geom_raster() + 
  geom_point(aes(alpha = id, colour = value), size = 12, shape = 15) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        strip.text.y = element_blank()) + 
  scale_fill_gradient(low = "darkblue", high = "lightblue") +
  ggtitle("test table") +
  facet_grid(rows = vars(test_data$category), 
             cols = vars(test_data$group),  scales = "free", space = "free_y") +
  scale_alpha_manual(values = c(rep(0, 19), 1, 0, 0), guide = guide_none()) +
  scale_color_gradientn(colours = c("red", "orange", "gold", "yellow"))

【讨论】:

    猜你喜欢
    • 2020-11-25
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 2011-08-17
    • 2018-04-09
    • 2019-12-23
    相关资源
    最近更新 更多