R ggplot heatmap avec plusieurs lignes ayant des légendes distinctes sur le même graphique

Aug 20 2020

J'essaie de créer une carte thermique en utilisant ggplot2 qui contient 3 types de variables où chacune a besoin de sa propre légende/échelle indépendante.

Je suis capable de les tracer tous dans une carte thermique (photo ci-dessous), mais j'ai du mal à les séparer pour avoir leur propre légende. Mes trois catégories sont la ligne "Score", "samp1" et le reste des données. J'aimerais que chacun d'eux ait ses propres légendes indépendantes avec ses gammes respectives.

Mon seul ajout serait que le score de ligne ait un jeu de couleurs vert, jaune, rouge (bas, moyen, élevé), si cela est possible à inclure dans cette question.

C'est le code que j'utilise pour créer ce graphique

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 

J'ai utilisé des facettes pour séparer les données par échantillon et par les 3 catégories que j'ai décrites ci-dessus. J'espérais utiliser ce regroupement pour créer également leurs propres légendes, mais je ne suis pas sûr que cela soit possible.

Cliquez ici pour télécharger les données (pré-fondues).

Merci en avance.

Réponses

3 stefan Aug 20 2020 at 03:03

Cela pourrait être réalisé via le ggnewscalepackage comme ceci:

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

Je suggérerais la prochaine approche. Divisez les données par groupes, puis créez un graphique séparé pour chaque groupe avec une fonction. Enfin, utilisez purrret patchworkpour joindre tous les tracés avec les différentes légendes. Ici le 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')

Le résultat:

Vous pouvez explorer plus en détail patchworket comment joindre plusieurs parcelles.

1 AllanCameron Aug 20 2020 at 03:24

Il est certes possible de faire 3 tracés et de les coller ensemble, mais étant donné que les facettes sont de formes différentes, ce n'est pas l'idéal. Vous pouvez utiliser le ggnewscalepackage selon Stefan, ce qui est plus facile maintenant qu'il est sur CRAN, mais si vous voulez le faire dans un seul ggplot sans add-ons, c'est possible . Il vous suffit de tracer un geom_pointcomposé de grands carrés pleins. Cela vous permet d'utiliser une échelle de couleurs ainsi qu'une échelle de remplissage.

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