R ggplot heatmap con più righe con legende separate sullo stesso grafico

Aug 20 2020

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

3 stefan Aug 20 2020 at 03:03

Ciò potrebbe essere ottenuto tramite il ggnewscalepacchetto 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()
  )

3 Duck Aug 20 2020 at 03:06

Suggerirei il prossimo approccio. Dividi i dati per gruppi e quindi crea un grafico separato per ciascun gruppo con una funzione. Infine usa purrre patchworkper 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 patchworke come unire più trame.

1 AllanCameron Aug 20 2020 at 03:24

È certamente possibile creare 3 trame e incollarle insieme, ma dato che le sfaccettature hanno forme diverse, non è l'ideale. Potresti usare il ggnewscalepacchetto 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_pointche è 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"))