Peta panas ggplot dengan beberapa baris yang memiliki legenda terpisah pada grafik yang sama
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
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()
)
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.
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"))
