web-dev-qa-db-fra.com

Ajuster l'espacement entre le texte dans la légende horizontale

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!

12
Mayou

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).

12
pangia
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)

horizontal_legend

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é.

14
Andre Silva

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)
1
RFelber

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

0
Shafiq