R ggplot mapa de calor con múltiples filas que tienen leyendas separadas en el mismo gráfico

Aug 20 2020

Estoy tratando de hacer un mapa de calor usando ggplot2 que contiene 3 tipos de variables donde cada una necesita su propia leyenda/escala independiente.

Puedo trazarlos a todos en un mapa de calor (en la imagen a continuación), pero tengo problemas para separarlos para tener su propia leyenda. Mis tres categorías son la fila "Puntuación", "muestra1" y el resto de los datos. Me gustaría que cada uno de estos tuviera sus propias leyendas independientes con sus respectivos rangos.

Mi única adición sería que la puntuación de la fila tenga un esquema de color verde, amarillo, rojo (bajo, medio, alto), si es posible incluirlo en esta pregunta.

Este es el código que estoy usando para crear ese gráfico.

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 

He usado facetas para separar los datos por muestra y por las 3 categorías que describí anteriormente. Tenía la esperanza de usar esta agrupación para crear sus propias leyendas también, pero no estoy seguro de si esto es posible.

Haga clic aquí para descargar los datos (pre-fundidos).

Gracias de antemano.

Respuestas

3 stefan Aug 20 2020 at 03:03

Esto podría lograrse a través del ggnewscalepaquete así:

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

Sugeriría el siguiente enfoque. Divida los datos por grupos y luego construya una gráfica separada para cada grupo con una función. Finalmente usa purrry patchworkpara unir todas las parcelas con las diferentes leyendas. Aquí el código:

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

La salida:

Puede explorar más sobre patchworky cómo unir múltiples parcelas.

1 AllanCameron Aug 20 2020 at 03:24

Ciertamente es posible hacer 3 tramas y unirlas, pero dado que las facetas tienen formas diferentes, esto no es lo ideal. Puede usar el ggnewscalepaquete según Stefan, que es más fácil ahora que está en CRAN, pero si desea hacerlo en un solo ggplot sin complementos, es posible. Solo necesita trazar una geom_pointque esté hecha de grandes cuadrados sólidos. Esto le permite usar una escala de color así como una escala de relleno.

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