J'ai une intrigue avec une légende horizontale:
legend("bottomleft", inset = c(0, -0.3), bty = "n",
x.intersp=0, xjust=0,yjust=0,
legend=c("AAPL", "Information Technology",
"Technology Hardware and Equipment", "S&P 500"),
col=c("black", "red", "blue3", "olivedrab3"),
lwd=2, cex = 0.5, xpd = TRUE, ncol = 4)
Le problème est qu’il existe un écart énorme entre le premier élément de la légende, "AAPL", et le deuxième élément "Technologies de l’information".
J'ai essayé d'ajuster l'espacement en utilisant txt.width()
, mais cela n'a pas fonctionné du tout. Ou peut-être que je n'utilise pas cette option comme indiqué. Voici comment j'ai introduit l'option txt.width
dans legend()
:
txt.width = c(2,1,1)
Je ne sais pas s'il est pertinent de le mentionner, mais mon axe des x est un axe des dates!
Existe-t-il un moyen simple de personnaliser les espaces entre le texte de la légende?
Merci!
text.width
peut vous donner le contrôle sur la largeur de chaque colonne de votre légende, mais ce n'est pas simple. text.width
est un vecteur qui sera multiplié par un autre vecteur aussi long que votre vecteur de chaînes de légende. Les éléments de ce second vecteur sont des entiers allant de 0
à length(legend)-1
. Voir le code à legend()
pour les détails sanglants. L'important est que vous puissiez considérer ce produit de text.width
et du second vecteur comme approximativement les coordonnées x de vos éléments de légende. Ensuite, si vous savez quelles coordonnées x vous voulez, vous pouvez calculer ce qui doit être passé dans l’argument text.width
.
legtext <- c("AAPL", "Information Technology",
"Technology Hardware and Equipment", "S&P 500")
xcoords <- c(0, 10, 30, 60)
secondvector <- (1:length(legtext))-1
textwidths <- xcoords/secondvector # this works for all but the first element
textwidths[1] <- 0 # so replace element 1 with a finite number (any will do)
Et ensuite, votre code final pourrait ressembler à ceci (sauf que nous ne connaissons pas vos données ou paramètres de traçage d'origine):
plot(x=as.Date(c("1/1/13","3/1/13","5/1/13"), "%m/%d/%y"), y=1:3, ylim=c(0,3))
legend(x="bottomleft", bty = "n", x.intersp=0, xjust=0, yjust=0,
legend=legtext,
col=c("black", "red", "blue3", "olivedrab3"),
lwd=2, cex = 0.5, xpd = TRUE, ncol = 4,
text.width=textwidths)
Comme Andre Silva l’a mentionné, les valeurs que vous souhaitez utiliser dans xcoords
et textwidths
dépendent de la taille actuelle de votre tracé, de la plage de valeurs spécifiée pour votre axe x, etc.
De plus, secondvector
ci-dessus serait différent si vous aviez plus d'un élément par colonne. Par exemple, pour deux colonnes avec deux éléments de légende chacun, secondvector == c(0,0,1,1)
.
plot(1,1,xlab="",ylab="",xlim=c(0,2),ylim=c(0,2))
legend("bottomleft", text.width=c(0,0.085,0.235,0.35),
inset = c(0, -0.2), bty = "n", x.intersp=0.5,
xjust=0, yjust=0,
legend=c("AAPL", "Information Technology",
"Technology Hardware and Equipment", "S&P 500"),
col=c("black", "red", "blue3", "olivedrab3"),
lwd=3, cex = 0.75, xpd = TRUE, horiz=TRUE)
J'ai utilisé text.width
avec quatre arguments pour définir l'espace entre les chaînes de la légende. Le deuxième argument à l'intérieur de text.width a permis de définir la distance entre "AAPL" et "Technologie de l'information", et ainsi de suite pour les troisième et quatrième arguments.
Malheureusement, je devais réinitialiser les valeurs dans text.width
chaque fois que je changeais la taille du tracé.
Sur mon système (plate-forme: x86_64-w64-mingw32, version R: 3.4.1 (2017-06-30)), les solutions fournies jusqu'à présent par Andre Silva et pangja ne sont pas satisfaisantes. Les deux solutions nécessitent une intervention de l'utilisateur et dépendent de la taille de l'appareil. Comme je ne me suis jamais habitué à la commande text.width
et que je devais toujours ajuster les valeurs avec try-and-error, j'ai écrit la fonction (f.horlegend
). La fonction a des arguments similaires à ceux de la fonction legend
et est basée sur l'idée affichée ici .
La fonction crée une légende horizontale (une ligne), qui peut être positionnée à l’aide des commandes connues à partir de la fonction legend
, par ex. "bottomleft"
f.horlegend <- function(pos, legend, xoff = 0, yoff = 0,
lty = 0, lwd = 1, ln.col = 1, seg.len = 0.04,
pch = NA, pt.col = 1, pt.bg = NA, pt.cex = par("cex"), pt.lwd = lwd,
text.cex = par("cex"), text.col = par("col"), text.font = NULL, text.vfont = NULL,
bty = "o", bbord = "black", bbg = par("bg"), blty = par("lty"), blwd = par("lwd"), bdens = NULL, bbx.adj = 0, bby.adj = 0.75
) {
### get original par values and re-set them at end of function
op <- par(no.readonly = TRUE)
on.exit(par(op))
### new par with dimension [0,1]
par(new=TRUE, xaxs="i", yaxs="i", xpd=TRUE)
plot.new()
### spacing between legend elements
d0 <- 0.01 * (1 + bbx.adj)
d1 <- 0.01
d2 <- 0.02
pch.len <- 0.008
ln.len <- seg.len/2
n.lgd <- length(legend)
txt.h <- strheight(legend[1], cex = text.cex, font = text.font, vfont = text.vfont) *(1 + bby.adj)
i.pch <- seq(1, 2*n.lgd, 2)
i.txt <- seq(2, 2*n.lgd, 2)
### determine x positions of legend elements
X <- c(d0 + pch.len, pch.len + d1, rep(strwidth(legend[-n.lgd])+d2+pch.len, each=2))
X[i.txt[-1]] <- pch.len+d1
### adjust symbol space if line is drawn
if (any(lty != 0)) {
lty <- rep(lty, n.lgd)[1:n.lgd]
ln.sep <- rep(ln.len - pch.len, n.lgd)[lty]
ln.sep[is.na(ln.sep)] <- 0
X <- X + rep(ln.sep, each=2)
lty[is.na(lty)] <- 0
}
X <- cumsum(X)
### legend box coordinates
bstart <- 0
bend <- X[2*n.lgd]+strwidth(legend[n.lgd])+d0
### legend position
if (pos == "top" | pos == "bottom" | pos == "center") x_corr <- 0.5 - bend/2 +xoff
if (pos == "bottomright" | pos == "right" | pos == "topright") x_corr <- 1. - bend + xoff
if (pos == "bottomleft" | pos == "left" | pos == "topleft") x_corr <- 0 + xoff
if (pos == "bottomleft" | pos == "bottom" | pos == "bottomright") Y <- txt.h/2 + yoff
if (pos == "left" | pos == "center" | pos =="right") Y <- 0.5 + yoff
if (pos == "topleft" | pos == "top" | pos == "topright") Y <- 1 - txt.h/2 + yoff
Y <- rep(Y, n.lgd)
### draw legend box
if (bty != "n") rect(bstart+x_corr, Y-txt.h/2, x_corr+bend, Y+txt.h/2, border=bbord, col=bbg, lty=blty, lwd=blwd, density=bdens)
### draw legend symbols and text
segments(X[i.pch]+x_corr-ln.len, Y, X[i.pch]+x_corr+ln.len, Y, col = ln.col, lty = lty, lwd = lwd)
points(X[i.pch]+x_corr, Y, pch = pch, col = pt.col, bg = pt.bg, cex = pt.cex, lwd = pt.lwd)
text(X[i.txt]+x_corr, Y, legend, pos=4, offset=0, cex = text.cex, col = text.col, font = text.font, vfont = text.vfont)
}
Arguments
pos
position de la légende (c ("bottomleft", "bottom", "bottomright", "gauche", "centre", "right", "topleft", "top", "toight"))
legend
légende
xoff
ajustement de la position dans la direction x. NB: la légende est tracée sur un graphique avec des limites = c (0,1)
yoff
idem que xoff mais dans y-directin
lty
Le type de ligne. Les types de ligne ne peuvent être spécifiés que sous la forme d'un entier (0 = vide, 1 = plein (valeur par défaut), 2 = pointillé, 3 = pointillé, 4 = pointillé, 5 = longdash, 6 = twodash).
lwd
La largeur de la ligne, un nombre positif, par défaut à 1
ln.col
La couleur de la ligne
seg.len
La longueur de la ligne, par défaut jusqu'à 0,04
pch
Un entier spécifiant le symbole.
pt.col
La couleur du symbole.
pt.bg
La couleur d'arrière-plan du symbole.
pt.cex
facteur d'expansion pour le symbole
pt.lwd
largeur de ligne du symbole
text.cex
facteur d'expansion pour le texte
text.col
couleur du texte
text.font
police de texte
text.vfont
voir vfont dans text-help
bty
le type de boîte à dessiner autour de la légende. Les valeurs autorisées sont "o" (valeur par défaut) et "n"
bbord
couleur de la bordure du cadre de légende
bbg
couleur de fond
blty
style de bordure
blwd
largeur de la ligne de bordure
bdens
densité de lignes, voir segment-help
bbx.adj
valeur relative pour augmenter l'espace entre le texte et la ligne horizontale
bby.adj
identique à bbx.adj mais pour la ligne verticale boc
Malheureusement, je n'ai pas le temps de créer un paquet pour le moment. Mais n'hésitez pas à utiliser la fonction. Tous les commentaires et idées pour améliorer les fonctions sont les bienvenus.
Quelques exemples
plot(1:100, rnorm(100))
lgd.text <- c("12", "12")
sapply(c("bottomleft", "bottom", "bottomright", "left", "center", "right", "topleft", "top", "topright"), function(x) f.horlegend(x, lgd.text, pch=16, lty=c(NA, 1), bbg="orange"))
plot(1:100, rnorm(100))
lgd.text <- c("12", "132", "12345")
f.horlegend("topleft", lgd.text, pch=NA)
f.horlegend("top", lgd.text, pch=NA, bby.adj=1.5, bbord="red")
f.horlegend("left", lgd.text, xoff=0.2, pch=1, bby.adj=0, bbord="red", bbg="lightgreen")
f.horlegend("left", lgd.text, xoff=0.2, yoff=-0.05, pch=c(NA, 1, 6), lty=1, bbx.adj=2, bby.adj=0, bbord="red", bbg="lightgreen")
f.horlegend("topright", lgd.text, yoff=0.1, pch=c(1,2,NA), lty=c(NA, NA, 2), bbord="red", blty=2, blwd=2)
lgd.text <- c("12", "123456", "12345", "123")
f.horlegend("bottom", lgd.text, yoff=0.1, pch=c(1,2,NA), lty=c(NA, 1, 2), text.font=2)
f.horlegend("bottom", lgd.text, pch=c(1,2,NA), lty=c(NA, 1, 2), text.font=c(1,2,3))
plot(seq(as.POSIXct("2017-08-30"), as.POSIXct("2017-09-30"), by="weeks"), rnorm(5), type="l")
f.horlegend("topleft", "random values", lty=1)
Pour mon cas, il y avait 5 légendes de manière horizontale. Je dois personnaliser l'espacement entre chaque légende. Voici l'extrait de code prévu à cet effet.
legend("topright",horiz = T, legend = df2, fill = col_box,
inset = c(-0.2,-0.1), xpd = TRUE, bty = 'n', density = density_value, angle = angle_value, x.intersp=0.3,
text.width=c(3.5,3.4,3.7,4.3,7))
C'était la fonction text.width
qui fait la magie