简体   繁体   English

调整水平图例中文本之间的间距

[英]Adjust spacing between text in horizontal legend

I have a plot with a horizontal legend:我有一个带有水平图例的情节:

 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)

text.width can give you control over the width of each column in your legend, but it's not straightforward. text.width可以让您控制图例中每一列的宽度,但这并不简单。 Basically, text.width is a vector that will be multiplied by another vector that is as long as your vector of legend strings.基本上, text.width是一个向量,它将乘以另一个与图例字符串向量一样长的向量。 The elements of that second vector are integers from 0 to length(legend)-1 .第二个向量的元素是从0length(legend)-1整数。 See the code to legend() for the gory details.有关血腥的详细信息,请参阅legend()代码 The important thing is that you can think of this product of text.width and the second vector as, approximately, the x coordinates for your legend elements.重要的是,您可以将text.width和第二个向量的text.width视为图例元素的近似 x 坐标。 Then if you know which x coordinates you want, you can calculate what needs to be passed in the text.width argument.然后如果你知道你想要哪个 x 坐标,你可以计算需要在text.width参数中传递的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)

And then your final code could look something like this (except that we don't know your original plotting data or parameters):然后你的最终代码可能看起来像这样(除了我们不知道你的原始绘图数据或参数):

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)

As Andre Silva mentioned, the values you'll want in xcoords and textwidths will depend on the current size of your plot, the range of values specified for your x axis, etc.正如安德烈席尔瓦所提到的,您需要在xcoordstextwidths的值将取决于您的绘图的当前大小、为您的 x 轴指定的值范围等。

Also, secondvector above would look different if you had more than one element per column.此外,如果每列有多个元素,上面的secondvector看起来会有所不同。 For example, for two columns with two legend elements apiece, secondvector == c(0,0,1,1) .例如,对于每列有两个图例元素的两列, 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)

水平图例

I used text.width with four arguments to set the space between strings in the legend.我使用带有四个参数的text.width来设置图例中字符串之间的空间。 The second argument inside text.width managed to set the distance between "AAPL" and "Information technology", and so on for the third and fourth arguments. text.width 中的第二个参数设法设置了“AAPL”和“信息技术”之间的距离,对于第三个和第四个参数,依此类推。

Unfortunately, I needed to reset the values inside text.width every time I changed the plot size.不幸的是,每次更改绘图大小时,我都需要重置text.width的值。

On my system (platform: x86_64-w64-mingw32, R version: 3.4.1 (2017-06-30)) the solutions provided so far by Andre Silva and pangja are not satisfactory.在我的系统(平台:x86_64-w64-mingw32,R 版本:3.4.1 (2017-06-30))上,Andre Silva 和 pangja 迄今为止提供的解决方案并不令人满意。 Both solutions require user input and are dependent on the device size.这两种解决方案都需要用户输入并取决于设备尺寸。 Since I get never used to the text.width command and always had to adjust the values with try-and-error, I wrote the function ( f.horlegend ).由于我从不习惯text.width命令并且总是不得不通过尝试和错误来调整值,因此我编写了函数 ( f.horlegend )。 The function has similar arguments as the function legend and is based on the idea posted here .该函数具有与函数legend类似的参数,并且基于此处发布的想法。

The function creates a horizontal (one row) legend, which can be positioned by the commands known from the function legend , eg "bottomleft"该函数创建一个水平(一行)图例,可以通过函数legend已知的命令定位,例如"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 of the legend (c("bottomleft", "bottom", "bottomright", "left", "center", "right", "topleft", "top", "topright")) pos图例的位置(c( “BOTTOMLEFT”, “底”, “bottomright”, “左”, “中心”, “右”, “左上”, “顶”, “topright”))

legend legend text legend图例文本

xoff adjustement of position in x-direction. xoff调整 x 方向的位置。 NB: the legend is plotted on a plot with limits = c(0,1)注意:图例绘制在一个图上,limits = c(0,1)

yoff same as xoff but in y-directin yoffyoff相同,但在 y 方向

lty The line type. lty线路类型。 Line types can only be specified as an integer (0=blank, 1=solid (default), 2=dashed, 3=dotted, 4=dotdash, 5=longdash, 6=twodash)线型只能指定为整数(0=空白,1=实线(默认),2=虚线,3=虚线,4=点划线,5=长划线,6=双划线)

lwd The line width, a positive number, defaulting to 1 lwd线宽,正数,默认为1

ln.col The line color ln.col线条颜色

seg.len The length of the line, deafult to 0.04 seg.len的长度,默认为 0.04

pch An integer specifying the symbol. pch指定符号的整数。

pt.col The symbol color. pt.col符号颜色。

pt.bg The background color of the symbol. pt.bg符号的背景颜色。

pt.cex expansion factor for the symbol pt.cex符号的扩展因子

pt.lwd line width of symbol pt.lwd符号线宽

text.cex expansion factor for the text文本的text.cex扩展因子

text.col text color text.col文字颜色

text.font text font text.font文本字体

text.vfont see vfont in text-help text.vfont请参阅文本帮助中的 vfont

bty the type of box to be drawn around the legend. bty要在图例周围绘制的框的类型。 The allowed values are "o" (the default) and "n"允许的值为“o”(默认值)和“n”

bbord color of the legend box border图例框边框的bbord颜色

bbg background color bbg背景色

blty border style blty边框样式

blwd border line width blwd边框线宽

bdens density of lines, see segment-help bdens线密度,请参阅段帮助

bbx.adj relative value to increase space between text and horizontal box line bbx.adj相对值增加文本和水平bbx.adj之间的空间

bby.adj same as bbx.adj but for vertical boc line bby.adjbby.adj相同,但用于垂直 boc 线

Unfortunately, I don't have time to create a package at the moment.不幸的是,我目前没有时间创建包。 But feel free to use the function.但请随意使用该功能。 Any comments and ideas to improve the functions are welcome.欢迎任何改进功能的意见和想法。

Some examples一些例子

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)

For my case, there were 5 legends in horizontal way.就我而言,水平方式有 5 个图例。 I have to customize the spacing between each legend.我必须自定义每个图例之间的间距。 Following was the code snippet for this purpose.以下是用于此目的的代码片段。

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

It was the text.width function that do the magictext.width函数发挥了神奇的作用

If anyone arrives at this same issue 7 years later, a technique I have found helpful is to set text.width with calls to the string width (strwidth) of each piece of legend text.如果有人在 7 年后遇到同样的问题,我发现有帮助的一种技术是设置 text.width 并调用每个图例文本的字符串宽度 (strwidth)。 This produces spacing which (to my eye) looks "natural" and can be modified by adding spaces to the strwidth argument.这会产生(在我看来)看起来“自然”的间距,并且可以通过向 strwidth 参数添加空格来修改。 For the posed question, it would look something like this:对于提出的问题,它看起来像这样:

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, text.width =
        c(strwidth("AAPL"), strwidth("Information Technology"), strwidth("Technology Hardware and Equipment"), strwidth("S&P 500"))
    )

This essentially does what Andre has suggested, but is a bit more user-friendly than manually defining the text width parameters by number.这基本上符合 Andre 的建议,但比按数字手动定义文本宽度参数更用户友好。

Based on the solution of pangia and the help of strwidth<\/code> , it is possible to calculate the x coordinates from the legend text:基于 pangia 的解决方案和strwidth<\/code>的帮助,可以从图例文本中计算 x 坐标:

### plot needs to be called first, so that strwidth can work
plot(x=as.Date(c("1/1/13","3/1/13","5/1/13"), "%m/%d/%y"), y=1:3, ylim=c(0,3))

legtext <- c("AAPL", "Information Technology", 
    "Technology Hardware and Equipment", "S&P 500")

### the following lines calculate the xcoords
### note that the cex argument in strwidth should be
### the same as in the legend call
xcoords <- c(0, cumsum( strwidth(legtext, cex = 0.5))[-length(legtext)])
secondvector <- (1:length(legtext))-1
textwidths <- xcoords/secondvector 
textwidths[1] <- 0 

legend(x="bottomleft", bty = "n", x.intersp=0.5, xjust=0, yjust=0,
    legend=legtext, 
    col=c("black", "red", "blue3", "olivedrab3"), 
    lwd=2, cex = 0.5, xpd = TRUE, ncol = 4,
    text.width=textwidths)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM