212 votes

Tracer une légende en dehors de la zone de traçage dans les graphiques de base ?

Comme le dit le titre : Comment puis-je tracer une légende en dehors de la zone de traçage lorsque j'utilise des graphiques de base ?

J'ai pensé à tripoter layout et produire un tracé vide pour ne contenir que la légende, mais je serais intéressé par une façon d'utiliser uniquement les facilités du graphique de base et par exemple, par(mar = ) pour avoir un peu d'espace à droite de la parcelle pour la légende.


Voici un exemple :

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
legend(1,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

produit :

alt text

Mais comme je l'ai dit, j'aimerais que la légende soit en dehors de la zone de traçage (par exemple, à droite du graphique/tracé).

0 votes

...vous pouvez également pirater le par avec un conteneur factice pour la légende, facile et assez pratique de temps en temps. Question similaire aquí .

5 votes

@hhh Le lien ne fonctionne plus. Pouvez-vous le mettre à jour ou poster une réponse en utilisant cette approche ?

166voto

Mike T Points 7385

Personne n'a mentionné l'utilisation des négatifs inset valeurs pour legend . Voici un exemple, où la légende est à droite du tracé, alignée en haut (en utilisant le mot-clé "topright" ).

# Random data to plot:
A <- data.frame(x=rnorm(100, 20, 2), y=rnorm(100, 20, 2))
B <- data.frame(x=rnorm(100, 21, 1), y=rnorm(100, 21, 1))

# Add extra space to right of plot area; change clipping to figure
par(mar=c(5.1, 4.1, 4.1, 8.1), xpd=TRUE)

# Plot both groups
plot(y ~ x, A, ylim=range(c(A$y, B$y)), xlim=range(c(A$x, B$x)), pch=1,
               main="Scatter plot of two groups")
points(y ~ x, B, pch=3)

# Add legend to top right, outside plot region
legend("topright", inset=c(-0.2,0), legend=c("A","B"), pch=c(1,3), title="Group")

La première valeur de inset=c(-0.2,0) peut nécessiter un ajustement en fonction de la largeur de la légende.

legend_right

14 votes

@Henrik non, cela ne fonctionne pas sans xpd=TRUE. Notez également qu'il est préférable de définir xpd=TRUE comme un argument de la fonction legend().

2 votes

Parfois xpd doit être réglé sur TRUE pour que l'encart négatif fonctionne. Mais parfois non. Avec la commande args.legend=list(x="bottom", horiz=TRUE, inset=-0.2) dans un barplot(... il ne semble pas avoir besoin xpd=TRUE mais avec seulement legend(x="bottom", horiz=TRUE, inset=-0.2) il semble qu'il faille xpd=TRUE . Des idées ? Je ne sais pas comment faire passer mes arguments ?

130voto

Spacedman Points 33792

Peut-être que ce dont vous avez besoin est par(xpd=TRUE) pour permettre aux choses d'être dessinées en dehors de la région du tracé. Donc si vous faites le tracé principal avec bty='L' vous aurez de la place sur la droite pour une légende. Normalement, celle-ci devrait être coupée à la région du tracé, mais faites par(xpd=TRUE) et avec un peu d'ajustement, vous pouvez obtenir une légende aussi droite que possible :

 set.seed(1) # just to get the same random numbers
 par(xpd=FALSE) # this is usually the default

 plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2), bty='L')
 # this legend gets clipped:
 legend(2.8,0,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

 # so turn off clipping:
 par(xpd=TRUE)
 legend(2.8,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

34 votes

Notez que vous pouvez passer xpd directement à legend afin de ne pas avoir à vous soucier de réinitialiser par par la suite. Voir aussi grconvertX & Y pour une façon de spécifier l'emplacement de la légende d'une manière qui ne dépend pas des limites des données que vous tracez.

7 votes

Comme cette question et cette réponse sont toujours très populaires, par(xpd=NA) est encore plus puissant (c.-à-d., des parcelles à plus de régions).

0 votes

+1. Nous devrions mentionner qu'il est judicieux d'avoir une section séparée par appel juste avant la légende. Dans mon graphique, j'ai utilisé par(new=T) à plusieurs autres occasions et je voulais simplement ajouter la xpd dans le même appel, ce qui pose problème.

38voto

Jan van der Laan Points 2348

Une autre solution, outre les ondes déjà mentionnées (utilisation de layout ou par(xpd=TRUE) ) consiste à superposer votre tracé avec un tracé transparent sur l'ensemble du dispositif, puis à y ajouter la légende.

L'astuce consiste à superposer un graphique (vide) sur la totalité de la zone de traçage et à y ajouter la légende. Nous pouvons utiliser la fonction par(fig=...) option. Tout d'abord, nous demandons à R de créer un nouveau tracé sur l'ensemble du dispositif de traçage :

par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), mar=c(0, 0, 0, 0), new=TRUE)

Réglage de oma et mar est nécessaire puisque nous voulons que l'intérieur du tracé couvre l'ensemble du dispositif. new=TRUE est nécessaire pour empêcher R de démarrer un nouveau dispositif. Nous pouvons alors ajouter le plot vide :

plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')

Et nous sommes prêts à ajouter la légende :

legend("bottomright", ...)

ajoutera une légende en bas à droite de l'appareil. De même, nous pouvons ajouter la légende à la marge supérieure ou droite. La seule chose dont nous devons nous assurer est que la marge du tracé original est suffisamment grande pour accueillir la légende.

En mettant tout ça dans une fonction ;

add_legend <- function(...) {
  opar <- par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), 
    mar=c(0, 0, 0, 0), new=TRUE)
  on.exit(par(opar))
  plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')
  legend(...)
}

Et un exemple. Tout d'abord, créez le graphique en vous assurant que nous avons suffisamment d'espace en bas pour ajouter la légende :

par(mar = c(5, 4, 1.4, 0.2))
plot(rnorm(50), rnorm(50), col=c("steelblue", "indianred"), pch=20)

Ajoutez ensuite la légende

add_legend("topright", legend=c("Foo", "Bar"), pch=20, 
   col=c("steelblue", "indianred"),
   horiz=TRUE, bty='n', cex=0.8)

Résultant en :

Example figure shown legend in top margin

2 votes

Excellent ajout à la liste ici. Il y a une explication sur la façon de faire fonctionner ceci avec plusieurs parcelles dans le graphique. aquí .

0 votes

Jan, existe-t-il un moyen d'augmenter la taille de la police dans la légende, sans que certains textes soient coupés ? Par exemple, j'ai un graphique comportant 4 types d'étiquettes différentes, mais avec beaucoup d'espace vide entre elles.

0 votes

J'ai écrit une question avec plus de détails stackoverflow.com/questions/42707308/

17voto

veiga Points 83

Désolé de ressusciter un vieux fil, mais j'ai eu le même problème aujourd'hui. La méthode la plus simple que j'ai trouvée est la suivante :

# Expand right side of clipping rect to make room for the legend
par(xpd=T, mar=par()$mar+c(0,0,0,6))

# Plot graph normally
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

# Plot legend where you want
legend(3.2,1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

# Restore default clipping rect
par(mar=c(5, 4, 4, 2) + 0.1)

Trouvé ici : http://www.harding.edu/fmccown/R/

4 votes

Encore mieux, oldpar <- par(xpd=T, mar=par()$mar+c(0,0,0,6)) ... par(oldpar) (Voir l'aide de par)

0 votes

Cette solution est meilleure car l'espace pour la légende est fixe, quelle que soit la longueur des chaînes de la légende.

10voto

Roman Luštrik Points 19295

Je ne peux offrir qu'un exemple de la solution de mise en page déjà signalée.

layout(matrix(c(1,2), nrow = 1), widths = c(0.7, 0.3))
par(mar = c(5, 4, 4, 2) + 0.1)
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
par(mar = c(5, 0, 4, 2) + 0.1)
plot(1:3, rnorm(3), pch = 1, lty = 1, ylim=c(-2,2), type = "n", axes = FALSE, ann = FALSE)
legend(1, 1, c("group A", "group B"), pch = c(1,2), lty = c(1,2))

an ugly picture :S

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X