R ggplot heatmap with multiple rows having separate legends on the same graph

跟風遠走 提交于 2021-01-27 20:07:00

问题


I'm trying to make one heatmap using ggplot2 that contains 3 types of variables where each need their own independent legend/scale.

I am able to plot them all in one heatmap (pictured below), but I am having trouble separating them to have their own legend. My three categories are the row "Score", "samp1" and the rest of the data. I would like each of these to have their own independent legends with their respective ranges.

My only addition would be to have the row score have a green,yellow,red (low, mid,high) color scheme, if that is possible to include in this question.

This is the code I am using to create that graph

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 

I have used facets to separate the data by sample and by the 3 categories I described above. I was hoping to use this grouping to create their own legends as well, but I am not sure if this is possible.

Click here to download the data (pre-melted).

Thank you in advance.


回答1:


This could be achieved via the ggnewscale package like so:

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:


I would suggest next approach. Split data by groups and then build a separate plot for each group with a function. Finally use purrr and patchwork to join all plots with the diferent legends. Here the code:

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')

The output:

You can explore further about patchwork and how to join multiple plots.




回答3:


It's certainly possible to make 3 plots and stick them together, but given the facets are different shapes, this isn't ideal. You could use the ggnewscale package as per Stefan, which is easier now it is on CRAN, but if you want to do it in a single ggplot without add-ons it is possible. You just need to plot a geom_point that is made of large solid squares. This allows you to use a colour scale as well as a fill scale.

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"))



来源:https://stackoverflow.com/questions/63493795/r-ggplot-heatmap-with-multiple-rows-having-separate-legends-on-the-same-graph

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!