Création d'une légende personnalisée dans r
J'espère avoir une légende qui inclut des références à toutes les couleurs, pas seulement les lignes verticales, et n'inclut pas de titre.
J'ai essayé scale_colour_manual et scale_fill_manual et ils se chevauchent tous ou n'affichent que les lignes verticales. J'apprécierais toutes suggestions.
Reprex est ci-dessous, y compris la palette de couleurs personnalisée.
var1 <- c(head(randu$x,n=12))
var2 <- as.Date(c("2010-01-01","2010-02-01","2010-03-01","2010-04-01","2010-05-01","2010-06-01","2010-07-01","2010-08-01","2010-09-01","2010-10-01","2010-11-01","2010-12-01"))
var3 <- c(tail(randu[which(randu$x + randu$y < 1),]$x,n=12))
var4 <- c(tail(randu[which(randu$x + randu$y < 1),]$y,n=12))
dat <- data.frame(var1,var2,var3,var4)
setDT(dat)
dat$var5 <- dat[,(var3+var4)]
new_dates <- as.Date(c("2010-09-01","2010-05-01"))
cbp2 <- c("#000000", "#56B4E9", "#009E73", "#0072B2", "#D55E00", "#CC79A7")
ggplot()+
geom_bar(data=dat,colour=cbp2[1],fill = cbp2[1],aes(x=var2,y=var5,colour="var4"),stat="identity")+
geom_bar(data=dat,colour=cbp2[2],fill = cbp2[2],aes(x=var2,y=var3,colour="var3"),stat="identity")+
geom_line(data=dat,colour=cbp2[1],aes(x=var2,y=var1))+
geom_vline(data=data.frame(xintercept = new_dates),
aes(xintercept = new_dates,linetype = "Changes", colour="red"),
linetype="dashed",key_glyph = "path")+
scale_color_manual(name = "",
values = c("red",cbp2[2],cbp2[1]),
breaks = c("red",cbp2[2],cbp2[1]),
labels = c("Changes","Var3","Var4"))+
scale_fill_manual(name = "",
values = c(cbp2[2],cbp2[1]),
breaks = c(cbp2[2],cbp2[1]),
labels = c("var3","var4"))+
ylab("")+
xlab("")+
scale_x_date(expand=c(0,0),date_breaks = "3 month", date_labels = "%b %y") +
scale_y_continuous(labels = function(var5) paste0(var5*100, "%"),
limits=c(0,1),
breaks=c(0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1)) +
theme(panel.background = element_blank(),
axis.line = element_line(colour = "#000000"),
axis.text.x = element_text(angle=60, hjust=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x= (element_text(margin = unit(c(3, 0, 0, 0), "mm"))),
legend.position = "top")
Il y a beaucoup de choses à déballer ici avec celui-ci, mais j'ai fait de mon mieux.
Tout d'abord, réfléchissez à ce que vous essayez de tracer ici. Normalement, ce n'est pas un problème d'appeler les choses var1, var2, var3,...
; cependant, dans ce contexte, c'est vraiment assez déroutant. Par conséquent, pour cette solution, je publierai à nouveau l'intégralité de votre code retravaillé au lieu de simplement la partie de traçage pour des raisons que j'espère décrire dans cette réponse.
Les données et la question
Cela étant dit, voici ma compréhension de la nature de l'ensemble de données et de votre désir pour le tracé final :
var2
dans l'ensemble de données contientDate
des informations sur la classe, et c'est l'x
axe commun pour l'ensemble du tracé.var1
contient des valeurs qui doivent être utilisées pour lesy
valeurs de lageom_line
couche de tracévar3
etvar4
contiennent des valeurs qui doivent être utilisées pour la création du barplot empilé qui devrait constituer l'arrière-plan du tracévar5
est une somme devar3 + var4
, et était un dispositif pour créer l'intrigue. Ici, cela ne sera pas utile, compte tenu de l'analyse des données que nous devons faire sur le jeu de données et de l'application des principes de Tidy Data.xintercept
Les valeurs de lageom_vline
couche de tracé sont fournies sous forme de deux datesnew_dates
La question du PO indique qu'il est nécessaire que la légende s'affiche correctement. Dans ce cas, nous voulons indiquer :
- couleur de remplissage des barres au fur
var3
et à mesurevar4
- la nature des lignes verticales sous forme de lignes rouges pointillées .. appelées « Changements »
- Une étiquette pour la
geom_line
couche de tracé. Supposons que l'étiquette seravar1
.
J'espère que tout était correct !
Synthétiser l'ensemble de données
J'encourage le PO à consulter l'utilisation de Tidy Data Principles , ce qui rendra la synthèse de données comme celle-ci beaucoup plus simple à l'avenir. Ici, j'appliquerai ces principes à l'ensemble de données dat
.
Tout d'abord, gérons les données de la couche de barres . En appliquant les principes Tidy données, nous voulons rassembler var3
et var4
créer sur les deux colonnes: (1) l' un pour le nom de la variable ( "var3"
ou "var4"
), et (2) un pour la valeur . Nous dirons ggplot2
d'"empiler" les barres, ce var5
n'est donc pas nécessaire ici : ggplot2
fera ce calcul automatiquement. Pour rassembler les colonnes, ma préférence est toujours d'utiliser gather()
from dplyr
et tidyr
:
library(dplyr)
library(tidyr)
library(ggplot2)
library(data.table)
var1 <- c(head(randu$x,n=12))
var2 <- as.Date(c("2010-01-01","2010-02-01","2010-03-01","2010-04-01","2010-05-01","2010-06-01","2010-07-01","2010-08-01","2010-09-01","2010-10-01","2010-11-01","2010-12-01"))
var3 <- c(tail(randu[which(randu$x + randu$y < 1),]$x,n=12))
var4 <- c(tail(randu[which(randu$x + randu$y < 1),]$y,n=12))
dat <- data.frame(var1,var2,var3,var4)
setDT(dat)
# dat$var5 <- dat[,(var3+var4)] no longer needed
new_dates <- as.Date(c("2010-09-01","2010-05-01"))
cbp2 <- c("#000000", "#56B4E9", "#009E73", "#0072B2", "#D55E00", "#CC79A7")
newdat <- dat %>%
gather(key='var_name', value='value', -var2) # gather all columns except for var2
names(newdat) <- c('Dates', 'var_name', 'value')
newdat$var_name <- factor(newdat$var_name, levels=c('var4', 'var3','var1'))
En plus de rassembler, vous noterez également que j'ajuste les noms des colonnes pour les rendre un peu plus faciles à suivre lorsqu'il s'agit de tracer. De plus, je définis l'ordre des niveaux pour newdat$var_name
. Le but ici est que l'ordre que nous spécifions se rapporte à l'ordre utilisé pour créer l'intrigue. Je veux var3
apparaître comme une barre "sous" var4
, nous devons donc spécifier que var4
c'est en premier.
Vous pouvez également créer un jeu de données séparé contenant var2
et var1
à utiliser pour tracer la geom_line
couche... mais cela fonctionne également très bien.
La parcelle
Pour l'intrigue, j'ai essayé d'organiser le code en sections distinctes. Ce que OP essayait de faire était de tracer colonne par colonne, plutôt que d'utiliser aes(fill=
et aes(color=
de définir et de créer des légendes. De plus, le code d'origine de l'OP contenait de nombreux exemples des éléments suivants :
geom_*(aes(color=...), color=...)
Le résultat de ceci ggplot2
est que si vous définissez une valeur esthétique (comme color=
) à l' extérieur de aes()
tout en indiquant également cet argument à l' intérieur aes()
, la valeur à l'extérieur écrasera la valeur spécifiée à l'intérieur du mappage - supprimant ainsi tout appel à placer cela dans une légende . C'était la principale cause de problème dans l'exemple du PO et pourquoi certains éléments étaient de la "bonne" couleur, mais n'apparaissaient dans aucune légende.
Spécifier des arguments dans aes()
indique uniquement qu'une légende doit être créée et indique ggplot2
sur quelle base appliquer la couleur, le remplissage, le type de ligne... cela ne spécifie pas réellement la couleur. La couleur doit être spécifiée à l'aide des scale_*_*()
fonctions. Dans ce cas, nous avons 3 types de légendes créés. L'OP peut s'organiser comme il le souhaite, mais j'ai essayé de garder cet exemple un peu illustratif pour permettre certains changements dans le cas de l'OP, car il n'est toujours pas tout à fait clair à quoi la légende doit ressembler complètement.
Notez qui values=
est utilisé pour appliquer la couleur, le type de ligne ou l'esthétique de remplissage, et se fait en alimentant cet argument en un vecteur nommé. Vous pouvez également utiliser un vecteur non nommé, auquel cas les attributs seront appliqués en fonction de l'ordre des niveaux pour ce facteur.
Notez que j'ai changé la couleur de la ligne du geom_line
en bleu... juste pour qu'il ressorte un peu. Ce serait un peu déroutant sinon, car il existe une couleur de remplissage qui est également noire.
ggplot(dat, aes(x=Dates, y=value)) +
# plot layers
geom_col(
data=subset(newdat, var_name != 'var1'),
aes(fill=var_name), position='stack') +
geom_line(
data=subset(newdat, var_name == 'var1'),
aes(color=var_name)
) +
geom_vline(data=data.frame(xintercept = new_dates),
aes(xintercept = new_dates, linetype = "Changes"), colour="red",
key_glyph = "path")+
# color and legend settings
scale_fill_manual(
name="Fill",
values=c('var3'=cbp2[2], 'var4'=cbp2[1])) +
scale_color_manual(
name='Color',
values = 'blue') +
scale_linetype_manual(
name='Linetype',
values=2) +
# scale adjustment and theme stuff
scale_y_continuous(labels = function(var5) paste0(var5*100, "%"),
limits=c(0,1),
breaks=c(0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1)) +
theme(panel.background = element_blank(),
axis.line = element_line(colour = "#000000"),
axis.text.x = element_text(angle=60, hjust=1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.title.x= (element_text(margin = unit(c(3, 0, 0, 0), "mm"))),
legend.position = "top")