2017-08-15 3 views
0

J'essaie de visualiser deux variables discrètes dans barplot avec ggplot2 en utilisant respectivement fill et alpha. La méthode standard pour ce faire est la suivante:r ggplot2: légende de regroupement dans les graphiques à barres

#creating data and building the basic bar plot 
library(ggplot2) 
myleg<-read.csv(text="lett,num 
a,1 
a,2 
b,1 
b,2 
h,1 
h,2 
h,3 
h,4") 
ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position=position_stack(reverse=T)) +scale_alpha_discrete(range=c(1,.1), name="alpha legend",labels=c("alpha lab 4","alpha lab 3","alpha lab 2", "alpha lab 1")) +labs(title="initial bar plot for data") 

initial bar plot of data

La légende par défaut sont groupés selon deux façons différentes de présentation (coloration pour lett et l'échelle de gris, ou d'opacité pour num).

Je dois avoir la légende groupée en tant que barres de données sur le tracé. c'est-à-dire trois bandes de couleur, chacune avec des niveaux alpha changeants. La solution partielle consiste à générer les parcelles avec trois désirées bandes de légende séparément comme suit:

ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position="stack",fill="#f8766d") +scale_alpha_discrete(name="red legend",labels=c("red lab 2","red lab 1"),breaks=c("3","4")) 
ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position="stack",fill="#00ba38") +scale_alpha_discrete(name="green legend",labels=c("green lab 2","green lab 1"),breaks=c("3","4")) 
ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position="stack",fill="#619cff") +scale_alpha_discrete(name="blue legend",labels=c("blue lab 4","blue lab 3","blue lab 2", "blue lab 1")) 

La sortie est: artificially created plots with needed legend strips

Donc pour l'instant je ne peux couper et coller trois bandes de légende sur le graphique principal , par exemple, dans Inkscape, pour produire le résultat souhaité:

final plot with desired legend

Comment il est possible de programmer de manière décente?

+0

réponse Marco ci-dessous est le « droit » de le faire, mais pour les chiffres particulièrement fiddly, à un moment donné votre façon de le faire dans Inkscape est la façon meilleure et plus personnalisable. – Brian

+0

J'ai édité ma réponse suggérant la solution pour le nouveau problème posté par @astrsk –

Répondre

4

Vous pouvez dessiner une légende personnalisée à l'aide scale_fill_manual:

df <- mtcars 
df$cyl <- factor(df$cyl) 
df$vs <- factor(df$vs) 

library(ggplot2)  
p <- ggplot(df,aes(x=cyl, fill=interaction(cyl,vs))) + geom_bar(position="stack") 

# Breaks 
brks <- levels(interaction(df$cyl,df$vs)) 

# Values - Colors 
library(scales) 
pal <- hue_pal()(3) 
cls <- as.character(c(sapply(pal,alpha,0.3),sapply(pal,alpha,1))) 

# Labels 
lbls <- paste(levels(df$cyl), "-", rep(levels(df$vs),each=3)) 

p + scale_fill_manual(name ='Cyl - Vs', breaks=brks, values=cls, labels=lbls) 

enter image description here

EDIT Voici une solution pour le problème (nouveau) posté par @astrsk (après sa/son changement de Question initiale).

façon
library(ggplot2) 
library(grid) 
library(gridExtra) 
myleg <- structure(list(lett = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 3L, 
3L), .Label = c("a", "b", "h"), class = "factor"), num = c(1L, 
2L, 1L, 2L, 1L, 2L, 3L, 4L)), .Names = c("lett", "num"), 
class = "data.frame", row.names = c(NA, -8L)) 

getLegend <- function(p) { 
    g <- ggplotGrob(p) 
    k <- which(g$layout$name=="guide-box") 
    g$grobs[[k]] 
} 

p1 <- ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position="stack",fill="#f8766d") +scale_alpha_discrete(name="red legend",labels=c("red lab 2","red lab 1"),breaks=c("3","4")) 
p2 <- ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position="stack",fill="#00ba38") +scale_alpha_discrete(name="green legend",labels=c("green lab 2","green lab 1"),breaks=c("3","4")) 
p3 <- ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) +geom_bar(position="stack",fill="#619cff") +scale_alpha_discrete(name="blue legend",labels=c("blue lab 4","blue lab 3","blue lab 2", "blue lab 1")) 

p <- ggplot(myleg,aes(lett,alpha=factor(num),fill=lett)) + 
    geom_bar(position=position_stack(reverse=T)) + 
    scale_alpha_discrete(range=c(1,.1), name="alpha legend", 
     labels=c("alpha lab 4","alpha lab 3","alpha lab 2", "alpha lab 1")) + 
    labs(title="initial bar plot for data") 
g <- ggplotGrob(p) 

k <- which(g$layout$name=="guide-box") 
g$grobs[[k]] <- grid.arrange(getLegend(p1),getLegend(p2),getLegend(p3),ncol=1) 
grid.draw(g) 

enter image description here

+0

Je dirais toujours que vos deux réponses sont la "bonne" manière de le faire :) Sortant la légende du gtables est assez lisse cependant! – Brian