it-swarm.com.de

Passen Sie den Abstand zwischen Text in der horizontalen Legende an

Ich habe eine Handlung mit einer horizontalen Legende:

 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)

Das Problem ist, dass zwischen dem ersten Element der Legende "AAPL" und dem zweiten Element "Information Technology" ein großer Abstand besteht.

Ich habe versucht, den Abstand mit txt.width() anzupassen, aber es funktionierte überhaupt nicht. Oder ich benutze diese Option möglicherweise nicht wie angegeben. So habe ich die txt.width-Option in legend() eingeführt:

txt.width = c(2,1,1)

Ich bin nicht sicher, ob es relevant ist zu erwähnen, aber meine X-Achse ist eine Datumsachse!

Gibt es eine einfache Möglichkeit, die Abstände zwischen dem Text in der Legende anzupassen?

Vielen Dank!

12
Mayou

Mit text.width können Sie die Breite jeder Spalte in Ihrer Legende steuern, dies ist jedoch nicht unkompliziert. Grundsätzlich ist text.width ein Vektor, der mit einem anderen Vektor multipliziert wird, der so lang ist wie Ihr Vektor von Legendenzeichenfolgen. Die Elemente dieses zweiten Vektors sind Ganzzahlen von 0 bis length(legend)-1. Siehe den Code zu legend() für die blutigen Details. Wichtig ist, dass Sie sich dieses Produkt aus text.width und dem zweiten Vektor als ungefähr die x-Koordinaten Ihrer Legendenelemente vorstellen können. Wenn Sie wissen, welche X-Koordinaten Sie benötigen, können Sie berechnen, was im Argument text.width übergeben werden muss.

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)

Und dann könnte Ihr endgültiger Code so aussehen (außer, dass wir Ihre ursprünglichen Zeichnungsdaten oder -parameter nicht kennen):

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)

Wie Andre Silva erwähnt hat, hängen die Werte, die Sie in xcoords und textwidths wünschen, von der aktuellen Größe Ihres Plots, dem Wertebereich für Ihre X-Achse usw. ab.

Darüber hinaus würde secondvector anders aussehen, wenn Sie mehr als ein Element pro Spalte hätten. Zum Beispiel für zwei Spalten mit je zwei Legendenelementen 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

Ich habe text.width mit vier Argumenten verwendet, um den Abstand zwischen den Zeichenfolgen in der Legende festzulegen. Das zweite Argument in text.width konnte den Abstand zwischen "AAPL" und "Informationstechnologie" festlegen, usw. für das dritte und vierte Argument.

Leider musste ich die Werte in text.width jedes Mal neu einstellen, wenn ich die Plotgröße änderte.

14
Andre Silva

Auf meinem System (Plattform: x86_64-w64-mingw32, R-Version: 3.4.1 (2017-06-30)) sind die bisher von Andre Silva und Pangja bereitgestellten Lösungen nicht zufriedenstellend. Beide Lösungen erfordern Benutzereingaben und sind von der Gerätegröße abhängig. Da ich mich nie an den text.width-Befehl gewöhnt habe und die Werte immer mit try-and-error anpassen musste, habe ich die Funktion (f.horlegend) geschrieben. Die Funktion hat ähnliche Argumente wie die Funktion legend und basiert auf der Idee hier .

Die Funktion erstellt eine horizontale Legende (eine Zeile), die durch die aus der Funktion legend bekannten Befehle positioniert werden kann, z. "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)

}

Argumente

pos Position der Legende (c ("bottomleft", "bottom", "bottomright", "left", "center", "right", "topleft", "top", "topright"))

legend Legendentext

xoff Anpassung der Position in x-Richtung. Hinweis: Die Legende wird in einer Grafik mit Grenzwerten = c (0,1) dargestellt.

yoff wie xoff aber in y-directin

lty Der Zeilentyp. Zeilentypen können nur als Ganzzahl angegeben werden (0 = leer, 1 = durchgezogen (Standard), 2 = gestrichelt, 3 = gepunktet, 4 = Punktdash, 5 = Longdash, 6 = Zweifach).

lwd Die Linienbreite, eine positive Zahl, standardmäßig auf 1 gesetzt

ln.col Die Linienfarbe

seg.len Die Länge der Zeile ist 0,04

pch Eine Ganzzahl, die das Symbol angibt.

pt.col Die Symbolfarbe.

pt.bg Die Hintergrundfarbe des Symbols.

pt.cex Erweiterungsfaktor für das Symbol

pt.lwd Linienbreite des Symbols

text.cex Erweiterungsfaktor für den Text

text.col Textfarbe

text.font Textschrift

text.vfont siehe vfont in der text-hilfe

bty Die Art der Box, die um die Legende gezeichnet werden soll. Die zulässigen Werte sind "o" (Standardeinstellung) und "n".

bbord Farbe des Rahmens der Legendenbox

bbg Hintergrundfarbe 

blty Rahmenstil

blwd Rahmenlinienbreite

bdens Liniendichte, siehe Segmenthilfe

bbx.adj relativer Wert, um den Abstand zwischen Text und horizontaler Rahmenzeile zu erhöhen

bby.adj wie bbx.adj, jedoch für vertikale Boc-Zeile 

Leider habe ich momentan keine Zeit, ein Paket zu erstellen. Aber nutzen Sie die Funktion. Alle Kommentare und Ideen zur Verbesserung der Funktionen sind willkommen.

Einige Beispiele

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

Für meinen Fall gab es 5 Legenden in horizontaler Richtung. Ich muss den Abstand zwischen den Legenden anpassen. Es folgte der Code-Ausschnitt für diesen Zweck.

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

Es war die text.width-Funktion, die die Magie ausübt

0
Shafiq