web-dev-qa-db-ja.com

水平凡例のテキスト間の間隔を調整する

水平凡例付きのプロットがあります:

_ 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」と2番目の項目「情報技術」の間に大きな間隔があることです。

txt.width()を使用して間隔を調整しようとしましたが、まったく機能しませんでした。または、指示どおりにこのオプションを使用していません。これは、legend()内に_txt.width_オプションを導入した方法です。

_txt.width = c(2,1,1)
_

それが言及に関連するかどうかはわかりませんが、私のx軸は日付の軸です!

凡例のテキスト間のスペースをカスタマイズする簡単な方法はありますか?

ありがとう!

13
Mayou

_text.width_を使用すると、凡例の各列の幅を制御できますが、簡単ではありません。基本的に、_text.width_は、凡例文字列のベクトルと同じ長さの別のベクトルで乗算されるベクトルです。その2番目のベクトルの要素は、_0_からlength(legend)-1までの整数です。詳細は code to legend() を参照してください。重要なことは、この_text.width_と2番目のベクトルの積を凡例の凡例要素の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)
_

Andre Silvaが述べたように、xcoordstextwidthsに必要な値は、プロットの現在のサイズ、x軸に指定された値の範囲などによって異なります。

また、列ごとに複数の要素がある場合、上記のsecondvectorは異なるように見えます。たとえば、2つの凡例要素が2つある2つの列の場合、secondvector == c(0,0,1,1)です。

13
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

text.widthを4つの引数とともに使用して、凡例の文字列間のスペースを設定しました。 text.width内の2番目の引数は、「AAPL」と「情報技術」の間の距離を設定することに成功し、3番目と4番目の引数についても同様です。

残念ながら、プロットサイズを変更するたびにtext.width内の値をリセットする必要がありました。

14
Andre Silva

私のシステム(プラットフォーム:x86_64-w64-mingw32、Rバージョン:3.4.1(2017-06-30))では、Andre Silvaとpangjaがこれまでに提供したソリューションは満足のいくものではありません。どちらのソリューションもユーザー入力を必要とし、デバイスのサイズに依存します。私はtext.widthコマンドに慣れず、常に試行錯誤で値を調整する必要があったため、関数(f.horlegend)を作成しました。この関数は、関数legendと同様の引数を持ち、投稿されたアイデア here に基づいています。

関数は、水平(1行)の凡例を作成します。凡例は、関数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方向の位置の調整。注意:凡例は、limits = c(0,1)のプロットにプロットされます

yoff xoffと同じですが、y-directinにあります

lty線種。線種は整数としてのみ指定できます(0 =空白、1 =実線(デフォルト)、2 =破線、3 =点線、4 =点線、5 =長い線、6 = 2線)

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テキストヘルプのvfontを参照

bty凡例の周囲に描画されるボックスのタイプ。許可される値は「o」(デフォルト)と「n」です。

bbord凡例ボックスの境界線の色

bbg背景色

bltyボーダースタイル

blwd境界線の幅

bdens行の密度、セグメントヘルプを参照

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

私の場合、水平方向に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魔法をかける関数

1
Shafiq