基本グラフィックスのプロットエリアの外側に凡例をプロットしますか?


185

タイトルが言うように:ベースグラフィックを使用しているときに、プロットエリアの外側に凡例をプロットするにはどうすればよいですか?

layout凡例をいじって空のプロットを作成することを考えましたが、基本的なグラフ機能だけを使用する方法に興味があります。たとえば、par(mar = )凡例のプロットの右側にスペースを確保します。


ここに例を示します:

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
legend(1,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

生成する:

代替テキスト

しかし、前述のように、凡例をプロットエリアの外側(たとえば、グラフ/プロットの右側)にしたいと考えています。


...また、凡例のダミーコンテナーを標準でハックすることもできます。ここで同様の質問。
hhh

3
@hhhリンクはもう機能していません。このアプローチを使用して、更新または回答を投稿できますか?
Henrik

回答:


111

多分あなたが必要とpar(xpd=TRUE)するのは物事がプロット領域の外に描かれることを可能にすることです。したがって、メインプロットを行うbty='L'と、右側に凡例用のスペースができます。通常、これはプロット領域にクリップされpar(xpd=TRUE)ますが、少し調整すると、凡例をできる限り右に取得できます。

 set.seed(1) # just to get the same random numbers
 par(xpd=FALSE) # this is usually the default

 plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2), bty='L')
 # this legend gets clipped:
 legend(2.8,0,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

 # so turn off clipping:
 par(xpd=TRUE)
 legend(2.8,-1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

33
xpdをlegendに直接渡すことができるため、後でparをリセットすることを心配する必要がないことに注意してください。プロットするデータの制限に依存しない方法で凡例の位置を指定する方法については、grconvertX&Yも参照してください。
Charles

6
この質問と回答はまだ非常に人気があるため、par(xpd=NA)さらに強力です(つまり、より多くの地域にプロットします)。
Henrik

+1。par凡例の直前に別の電話をかけるのは理にかなっていることを述べておかなければなりません。私のプロットでは、par(new=T)他のいくつかの場面で使用しxpd、同じ呼び出しでparam を追加するだけで問題が発生していました。
Matt Bannert 2016

146

に負のinset値を使用することについて言及した人はいませんlegend。これは、凡例がプロットの右側にあり、上に揃えられている例です(keywordを使用"topright")。

# Random data to plot:
A <- data.frame(x=rnorm(100, 20, 2), y=rnorm(100, 20, 2))
B <- data.frame(x=rnorm(100, 21, 1), y=rnorm(100, 21, 1))

# Add extra space to right of plot area; change clipping to figure
par(mar=c(5.1, 4.1, 4.1, 8.1), xpd=TRUE)

# Plot both groups
plot(y ~ x, A, ylim=range(c(A$y, B$y)), xlim=range(c(A$x, B$x)), pch=1,
               main="Scatter plot of two groups")
points(y ~ x, B, pch=3)

# Add legend to top right, outside plot region
legend("topright", inset=c(-0.2,0), legend=c("A","B"), pch=c(1,3), title="Group")

の最初の値はinset=c(-0.2,0)、凡例の幅に基づいて調整する必要がある場合があります。

legend_right


14
@Henrikいいえ、xpd = TRUEがないと機能しません。また、legend()関数の引数としてxpd = TRUEを設定することをお勧めします。
ステファン・ローラン

1
ネガティブインセットが機能するxpdように設定する必要がある場合がありますTRUE。しかし、時にはそうではありません。args.legend=list(x="bottom", horiz=TRUE, inset=-0.2)a内のコマンドではbarplot(...必要ないようですxpd=TRUEが、legend(x="bottom", horiz=TRUE, inset=-0.2)それだけで必要なようですxpd=TRUE。洞察はありますか?私は私の引数を渡すことで混乱していますか?
user3386170

28

別の解決策として、すでに述べたオンデス(layoutまたはを使用par(xpd=TRUE))のほかに、デバイス全体の透明なプロットでプロットをオーバーレイし、それに凡例を追加する方法があります。

トリックは、完全なプロット領域に(空の)グラフをオーバーレイし、それに凡例を追加することです。par(fig=...)オプションを使用できます。まず、Rにプロットデバイス全体に新しいプロットを作成するように指示します。

par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), mar=c(0, 0, 0, 0), new=TRUE)

プロットの内部がデバイス全体をカバーするようにしたいので、設定omaおよびmar必要です。new=TRUERが新しいデバイスを起動しないようにするために必要です。次に、空のプロットを追加できます。

plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')

そして、凡例を追加する準備が整いました:

legend("bottomright", ...)

デバイスの右下に凡例を追加します。同様に、凡例を上または右マージンに追加できます。確認する必要がある唯一のことは、元のプロットのマージンが凡例を収容するのに十分な大きさであることです。

これらすべてを関数に入れます。

add_legend <- function(...) {
  opar <- par(fig=c(0, 1, 0, 1), oma=c(0, 0, 0, 0), 
    mar=c(0, 0, 0, 0), new=TRUE)
  on.exit(par(opar))
  plot(0, 0, type='n', bty='n', xaxt='n', yaxt='n')
  legend(...)
}

そして例。最初に、凡例を追加するために下部に十分なスペースがあることを確認して、プロットを作成します。

par(mar = c(5, 4, 1.4, 0.2))
plot(rnorm(50), rnorm(50), col=c("steelblue", "indianred"), pch=20)

次に、凡例を追加します

add_legend("topright", legend=c("Foo", "Bar"), pch=20, 
   col=c("steelblue", "indianred"),
   horiz=TRUE, bty='n', cex=0.8)

その結果:

上余白に凡例を示す図の例


2
ここのリストへの素晴らしい追加。この図の複数のプロットでこれを機能させる方法についての説明があります
shiri

1月、一部のテキストが切り取られずに、凡例のフォントサイズを大きくする方法はありますか?たとえば、グラフィックには4種類のラベルがありますが、それらの間にたくさんの空白スペースがあります。
海の老人。


16

古いスレッドを復活させて申し訳ありませんが、私は今日同じ問題を抱えていました。私が見つけた最も簡単な方法は次のとおりです:

# Expand right side of clipping rect to make room for the legend
par(xpd=T, mar=par()$mar+c(0,0,0,6))

# Plot graph normally
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

# Plot legend where you want
legend(3.2,1,c("group A", "group B"), pch = c(1,2), lty = c(1,2))

# Restore default clipping rect
par(mar=c(5, 4, 4, 2) + 0.1)

ここにあります:http : //www.harding.edu/fmccown/R/


4
oldpar <-par(xpd = T、mar = par()$ mar + c(0,0,0,6))... par(oldpar)(parのヘルプを参照)
rakensi

凡例の間隔は凡例の文字列の長さに関係なく固定されるため、このソリューションの方が優れています
Sergio

15

私はそれをこのようにするのが好きです:

par(oma=c(0, 0, 0, 5))
plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch=2, lty=2, type="o")
legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA,
       c("group A", "group B"), pch=c(1, 2), lty=c(1,2))

ここに画像の説明を入力してください

必要な唯一の微調整は、凡例に対応するのに十分な幅に右マージンを設定することです。

ただし、これは自動化することもできます。

dev.off() # to reset the graphics pars to defaults
par(mar=c(par('mar')[1:3], 0)) # optional, removes extraneous right inner margin space
plot.new()
l <- legend(0, 0, bty='n', c("group A", "group B"), 
            plot=FALSE, pch=c(1, 2), lty=c(1, 2))
# calculate right margin width in ndc
w <- grconvertX(l$rect$w, to='ndc') - grconvertX(0, to='ndc')
par(omd=c(0, 1-w, 0, 1))
plot(1:3, rnorm(3), pch=1, lty=1, type="o", ylim=c(-2, 2))
lines(1:3, rnorm(3), pch=2, lty=2, type="o")
legend(par('usr')[2], par('usr')[4], bty='n', xpd=NA,
       c("group A", "group B"), pch=c(1, 2), lty=c(1, 2))

ここに画像の説明を入力してください


xpd = Tまたはxpd = NAを使用しても、「main」(タイトル)が引き伸ばされて右マージンが広い領域を使用しようとしたときにクリップされないようにすることはできません。
Phil Goetz

@PhilGoetzプロットエリア内でメインをプロットしていますか?あなたがそこにプロットするのに十分なマージンラインがないのは可能ですか?
jbaums 2016年

10

最近、凡例をプロットエリアの外側に印刷する非常に簡単で興味深い機能を見つけました。

プロットの右側に外側マージンを作成します。

par(xpd=T, mar=par()$mar+c(0,0,0,5))

プロットを作成する

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

凡例を追加し、以下のようにlocator(1)関数を使用します。次に、次のスクリプトを読み込んだ後、必要な場所をクリックするだけです。

legend(locator(1),c("group A", "group B"), pch = c(1,2), lty = c(1,2))

それを試してみてください


9

私はすでに指摘したレイアウトソリューションの例のみを提供できます。

layout(matrix(c(1,2), nrow = 1), widths = c(0.7, 0.3))
par(mar = c(5, 4, 4, 2) + 0.1)
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")
par(mar = c(5, 0, 4, 2) + 0.1)
plot(1:3, rnorm(3), pch = 1, lty = 1, ylim=c(-2,2), type = "n", axes = FALSE, ann = FALSE)
legend(1, 1, c("group A", "group B"), pch = c(1,2), lty = c(1,2))

醜い絵:S


9

私の意見では非常にエレガントな別の単純な代替を追加します。

あなたのプロット:

plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

伝説:

legend("bottomright", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
       inset=c(0,1), xpd=TRUE, horiz=TRUE, bty="n"
       )

結果:

伝説の絵

ここでは、凡例の2行目のみが例に追加されています。順番に:

  • inset=c(0,1)-(x、y)方向にプロット領域の割合で凡例を移動します。この場合、凡例は適切な"bottomright"位置にあります。これは、x方向に0プロット領域(したがって、「右」に留まる)とy方向(下から上)に1プロット領域だけ移動します。そして、たまたまそれがプロットの真上に現れる。
  • xpd=TRUE -凡例をプロット領域外に表示してみましょう。
  • horiz=TRUE -水平方向の凡例を作成するように指示します。
  • bty="n" -凡例の境界ボックスを取り除くためのスタイルの詳細。

サイドに凡例を追加する場合も同様です。

par(mar=c(5,4,2,6))
plot(1:3, rnorm(3), pch = 1, lty = 1, type = "o", ylim=c(-2,2))
lines(1:3, rnorm(3), pch = 2, lty = 2, type="o")

legend("topleft", c("group A", "group B"), pch=c(1,2), lty=c(1,2),
       inset=c(1,0), xpd=TRUE, bty="n"
       )

ここでは、凡例の位置を調整し、プロットの右側にマージンスペースを追加しました。結果:

凡例2の画像


4

これは、Plotly R APIを使用するか、コードを使用するか、凡例を必要な場所にドラッグしてGUIから実行できます。

例を示します。グラフとコードもここにあります

x = c(0,1,2,3,4,5,6,7,8) 
y = c(0,3,6,4,5,2,3,5,4) 
x2 = c(0,1,2,3,4,5,6,7,8) 
y2 = c(0,4,7,8,3,6,3,3,4)

凡例をグラフの外側に配置するには、x値とy値のいずれかを100または-100のいずれかに割り当てます。

legendstyle = list("x"=100, "y"=1)
layoutstyle = list(legend=legendstyle)

その他のオプションは次のとおりです。

  • list("x" = 100, "y" = 0) 外側右下用
  • list("x" = 100, "y"= 1) 右上の外側
  • list("x" = 100, "y" = .5) 右中外
  • list("x" = 0, "y" = -100) 左下
  • list("x" = 0.5, "y" = -100) アンダーセンター
  • list("x" = 1, "y" = -100) 右下

次に応答。

response = p$plotly(x,y,x2,y2, kwargs=list(layout=layoutstyle));

呼び出しを行うと、PlotlyはグラフとともにURLを返します。を呼び出すと、よりすばやくアクセスできbrowseURL(response$url)、ブラウザでグラフが開きます。

url = response$url
filename = response$filename

それがこのグラフです。また、GUI内から凡例を移動すると、それに応じてグラフがスケーリングされます。完全な開示:Plotlyチームに所属しています。

グラフの横の凡例


2

layout()下で空のプロットを作成し、1/4程度に適切にスケーリングして、凡例のパーツを手動で配置することで、過去にこれに使用したものを試してください。

ここlegend()にあなたが始めるべきであるいくつかの古い質問があります。


すでに質問で述べたように、これも私が考えたものです。しかし、別の方法があれば理想的です。どういうわけか私はないと思います。
Henrik
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.