Peta panas ggplot dengan beberapa baris yang memiliki legenda terpisah pada grafik yang sama

Aug 20 2020

Saya mencoba membuat satu peta panas menggunakan ggplot2 yang berisi 3 jenis variabel di mana masing-masing membutuhkan legenda / skala independennya sendiri.

Saya bisa memplot semuanya dalam satu peta panas (gambar di bawah), tetapi saya kesulitan memisahkan mereka untuk memiliki legenda sendiri. Tiga kategori saya adalah baris "Skor", "samp1", dan data lainnya. Saya ingin masing-masing memiliki legenda independen dengan rentang masing-masing.

Satu-satunya tambahan saya adalah membuat skor baris memiliki skema warna hijau, kuning, merah (rendah, sedang, tinggi), jika memungkinkan untuk disertakan dalam pertanyaan ini.

Ini adalah kode yang saya gunakan untuk membuat grafik itu

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.

Jawaban

3 stefan Aug 20 2020 at 03:03

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

3 Duck Aug 20 2020 at 03:06

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.

1 AllanCameron Aug 20 2020 at 03:24

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