Supposons que j'ai l'intrigue suivante dans ggplot:
Il a été généré à l'aide du code ci-dessous:
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df.merged <- rbind(df1, df2, df3, df4)
ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
Je voudrais avoir une seule légende qui affiche correctement les formes, les couleurs et les types de lignes (la légende d'interaction (Type, Méthode) est la plus proche de ce que je voudrais, mais elle n'a pas les types de formes/lignes corrects) .
Je sais que si j'utilise scale_xxx_manual et que je spécifie les mêmes étiquettes pour toutes les légendes, elles seront fusionnées, mais je ne souhaite pas avoir à les définir manuellement: s'il existe de nouvelles méthodes ou Types, je ne veux pas avoir à modifier mon code : un désir quelque chose de générique.
Comme indiqué dans les réponses ci-dessous, il existe plusieurs façons de faire le travail dans ce cas particulier. Toutes les solutions proposées nécessitent de définir manuellement les types et les formes de ligne de légende, soit à l'aide de scale_xxx_manual function
S, soit à l'aide de la fonction guides
.
Cependant, les solutions proposées ne fonctionnent toujours pas dans le cas général: par exemple, si j'ajoute un nouveau bloc de données à l'ensemble de données avec une nouvelle méthode "method3", cela ne fonctionne plus, nous devons ajouter manuellement le nouveau légende formes et types de lignes:
y5 <- sin(x - pi / 4)
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
df.merged <- rbind(df1, df2, df3, df4, df5)
override.shape <- c(16, 17, 16, 17, 16)
override.linetype <- c(1, 1, 3, 3, 4)
g <- ggplot(df.merged, aes(x, y, colour = interaction(Type, Method), linetype = Method, shape = Type)) + geom_line() + geom_point()
g <- g + guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype)))
g <- g + scale_shape(guide = FALSE)
g <- g + scale_linetype(guide = FALSE)
print(g)
Cela donne:
Maintenant, la question est: comment générer automatiquement les vecteurs override.shape
Et override.linetype
?
Notez que la taille du vecteur est 5 car nous avons 5 courbes, alors que le facteur interaction(Type, Method)
a la taille 6 (je n'ai pas de données pour la combinaison cos/method3)
Voici la solution dans le cas général:
# Create the data frames
x <- seq(0, 10, by = 0.2)
y1 <- sin(x)
y2 <- cos(x)
y3 <- cos(x + pi / 4)
y4 <- sin(x + pi / 4)
y5 <- sin(x - pi / 4)
df1 <- data.frame(x, y = y1, Type = as.factor("sin"), Method = as.factor("method1"))
df2 <- data.frame(x, y = y2, Type = as.factor("cos"), Method = as.factor("method1"))
df3 <- data.frame(x, y = y3, Type = as.factor("cos"), Method = as.factor("method2"))
df4 <- data.frame(x, y = y4, Type = as.factor("sin"), Method = as.factor("method2"))
df5 <- data.frame(x, y = y5, Type = as.factor("sin"), Method = as.factor("method3"))
# Merge the data frames
df.merged <- rbind(df1, df2, df3, df4, df5)
# Create the interaction
type.method.interaction <- interaction(df.merged$Type, df.merged$Method)
# Compute the number of types and methods
nb.types <- nlevels(df.merged$Type)
nb.methods <- nlevels(df.merged$Method)
# Set the legend title
legend.title <- "My title"
# Initialize the plot
g <- ggplot(df.merged, aes(x,
y,
colour = type.method.interaction,
linetype = type.method.interaction,
shape = type.method.interaction)) + geom_line() + geom_point()
# Here is the magic
g <- g + scale_color_discrete(legend.title)
g <- g + scale_linetype_manual(legend.title,
values = rep(1:nb.types, nb.methods))
g <- g + scale_shape_manual(legend.title,
values = 15 + rep(1:nb.methods, each = nb.types))
# Display the plot
print(g)
Le résultat est le suivant:
Pour résumer, les astuces sont les suivantes:
interaction
pour toutes les représentations de données (couleur, forme, type de ligne, etc.)scale_xxx_manual
.scale_xxx_manual
vous permet de fournir un vecteur de valeurs plus long que le nombre réel de courbes. Il est donc facile de calculer les valeurs de vecteur de style à partir de la taille des facteurs Type et Méthode.J'ai eu ce problème l'autre jour. La section R Cookbook sur Legends explique:
Si vous utilisez à la fois la couleur et la forme, vous devez indiquer les deux spécifications de l'échelle. Sinon, il y aura deux deux légendes distinctes.
Dans votre cas, vous avez besoin de spécifications pour shape
et linetype
.
Modifier
Il était important que les mêmes données créent les formes, les couleurs et les lignes. J'ai combiné votre phase d'interaction en définissant directement la colonne. Au lieu de scale_linetype_discrete
pour créer la légende, j’ai utilisé scale_linetype_manual
pour spécifier les valeurs car elles prendront quatre valeurs différentes par défaut.
Si vous souhaitez une mise en page détaillée de toutes les formes et types de lignes possibles, cochez this R Graphics site pour afficher tous les identificateurs de numéro:
df.merged$int <- paste(df.merged$Type, df.merged$Method, sep=".")
ggplot(df.merged, aes(x, y, colour = int, linetype=int, shape=int)) +
geom_line() +
geom_point() +
scale_colour_discrete("") +
scale_linetype_manual("", values=c(1,2,1,2)) +
scale_shape_manual("", values=c(17,17,16,16))
Utilisez labs()
et définissez la même valeur pour toutes les esthétiques définissant l'apparence des zones géographiques.
library('ggplot2')
ggplot(iris) +
aes(x = Sepal.Length, y = Sepal.Width,
color = Species, linetype = Species, shape = Species) +
geom_line() +
geom_point() +
labs(color = "Guide name", linetype = "Guide name", shape = "Guide name")
Il suffit de nommer les deux guides de la même manière. Par exemple:
g+ scale_linetype_manual(name="Guide1",values= c('solid', 'solid', 'dotdash'))+
scale_colour_manual(name="Guide1", values = c("blue", "green","red"))
Le code ci-dessous donne la légende souhaitée, si je comprends votre question, mais je ne suis pas sûr de comprendre le problème de l'étiquette, alors laissez-moi savoir si ce n'est pas ce que vous recherchiez.
p = ggplot(df.merged, aes(x, y, colour=interaction(Type, Method),
linetype=interaction(Type, Method),
shape=interaction(Type, Method))) +
geom_line() +
geom_point()
p + scale_shape_manual(values=rep(16:17, 2)) +
scale_linetype_manual(values=rep(c(1,3),each=2))