我有一个带有水平图例的情节:
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)
问题是图例的第一项“AAPL”和第二项“信息技术”之间存在巨大的间距。
我尝试使用txt.width()
调整间距,但它根本不起作用。或者我可能没有按照指示使用此选项。这就是我在txt.width
中引入legend()
选项的方法:
txt.width = c(2,1,1)
我不确定它是否与提及相关,但我的x轴是日期轴!
是否有一种简单的方法可以自定义图例中文本之间的空格?
谢谢!
答案 0 :(得分:14)
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)
我使用text.width
和四个参数来设置图例中字符串之间的空格。 text.width中的第二个参数设法设置“AAPL”和“信息技术”之间的距离,依此类推第三个和第四个参数。
不幸的是,每次更改绘图大小时,我都需要重置text.width
内的值。
答案 1 :(得分:13)
text.width
可以让您控制图例中每列的宽度,但这并不简单。基本上,text.width
是一个向量,它将乘以另一个向量,该向量与图例字符串的向量一样长。第二个向量的元素是从0
到length(legend)-1
的整数。有关血腥的详细信息,请参阅code to legend()
。重要的是你可以将text.width
和第二个向量的这个乘积想象成近似于图例元素的x坐标。然后,如果您知道需要哪个x坐标,则可以计算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)
然后你的最终代码看起来像这样(除了我们不知道你原来的绘图数据或参数):
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)
正如安德烈·席尔瓦所提到的,xcoords
和textwidths
中您想要的值将取决于您的绘图的当前大小,为x轴指定的值范围等。
此外,如果每列有多个元素,则上面的secondvector
会有所不同。例如,对于两个具有两个图例元素的列,secondvector == c(0,0,1,1)
。
答案 2 :(得分:3)
在我的系统上(平台:x86_64-w64-mingw32,R版本:3.4.1(2017-06-30))目前由Andre Silva和pangja提供的解决方案并不令人满意。两种解决方案都需要用户输入,并且取决于设备大小。由于我从未习惯text.width
命令并且总是必须通过try-and-error调整值,因此我编写了函数(f.horlegend
)。该函数具有与函数legend
类似的参数,并基于发布here的想法。
该函数创建一个水平(一行)图例,该图例可以通过函数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)
}
<强>参数强>
pos
传奇的位置(c(“bottomleft”,“bottom”,“bottomright”,“left”,“center”,“right”,“topleft”,“top”,“topright” ))
legend
传奇文字
xoff
调整x方向的位置。注意:图例绘制在极限= c(0,1)
yoff
与xoff相同,但在y-directin
lty
线型。线型只能指定为整数(0 =空白,1 =实线(默认),2 =虚线,3 =点线,4 = dotdash,5 = longdash,6 = twodash)
lwd
线宽,正数,默认为1
ln.col
线条颜色
seg.len
该行的长度,取消为0.04
pch
指定符号的整数。
pt.col
符号颜色。
pt.bg
符号的背景颜色。
pt.cex
扩展因子
pt.lwd
符号的线宽
text.cex
扩展因子
text.col
文字颜色
text.font
文字字体
text.vfont
请参阅text-help中的vfont
bty
围绕图例绘制的框的类型。允许的值为“o”(默认值)和“n”
bbord
图例框边框的颜色
bbg
背景色
blty
边框样式
blwd
边框线宽
bdens
,请参阅segment-help
bbx.adj
相对值,用于增加文字和水平方框之间的空间
bby.adj
与bbx.adj相同,但对于垂直boc行
不幸的是,我目前没有时间创建包。但随意使用该功能。欢迎任何改进功能的意见和想法。
一些例子
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)
答案 3 :(得分:0)
就我而言,水平有5个图例。我必须自定义每个图例之间的间距。以下是用于此目的的代码段。
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))
发挥作用的是text.width
函数
答案 4 :(得分:0)
如果有人在 7 年后遇到同样的问题,我发现一种有用的技术是设置 text.width 并调用每个图例文本的字符串宽度 (strwidth)。这会产生(在我看来)看起来“自然”的间距,并且可以通过向 strwidth 参数添加空格来修改。对于提出的问题,它看起来像这样:
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"))
)
这基本上符合 Andre 的建议,但比通过数字手动定义文本宽度参数更方便用户使用。