R ggplot heatmap con più righe con legende separate sullo stesso grafico
Sto cercando di creare una mappa di calore utilizzando ggplot2 che contenga 3 tipi di variabili in cui ciascuna necessita della propria legenda/scala indipendente.
Sono in grado di tracciarli tutti in una mappa di calore (nella foto sotto), ma ho problemi a separarli per avere la loro legenda. Le mie tre categorie sono la riga "Score", "samp1" e il resto dei dati. Vorrei che ognuno di questi avesse le proprie leggende indipendenti con le rispettive gamme.
La mia unica aggiunta sarebbe che il punteggio della riga avesse uno schema di colori verde, giallo, rosso (basso, medio, alto), se è possibile includerlo in questa domanda.

Questo è il codice che sto usando per creare quel grafico
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
Ho utilizzato i facet per separare i dati per campione e per le 3 categorie che ho descritto sopra. Speravo di utilizzare questo raggruppamento anche per creare le proprie leggende, ma non sono sicuro che sia possibile.
Clicca qui per scaricare i dati (prefuso).
Grazie in anticipo.
Risposte
Ciò potrebbe essere ottenuto tramite il ggnewscale
pacchetto in questo modo:
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()
)
Suggerirei il prossimo approccio. Dividi i dati per gruppi e quindi crea un grafico separato per ciascun gruppo con una funzione. Infine usa purrr
e patchwork
per unire tutte le trame con le diverse leggende. Qui il codice:
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')
L'output:

Puoi esplorare ulteriormente patchwork
e come unire più trame.
È certamente possibile creare 3 trame e incollarle insieme, ma dato che le sfaccettature hanno forme diverse, non è l'ideale. Potresti usare il ggnewscale
pacchetto come per Stefan, che è più facile ora che è su CRAN, ma se vuoi farlo in un singolo ggplot senza componenti aggiuntivi è possibile. Hai solo bisogno di tracciare un geom_point
che è fatto di grandi quadrati solidi. Ciò consente di utilizzare una scala di colori e una scala di riempimento.
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"))
