0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rでグラフの凡例の幅が大きくなってしまう現象とその回避策

Posted at

Rで出力したグラフにlegend()関数を使って凡例を書き込んだところ、凡例のボックスの幅が広がって文字列の右側に余白ができてしまう現象にハマった。そのワークアラウンドです。

実行環境
R 4.3.0, macOS 12.6.5

サンプルのコードはこれです。今回プロット領域の外側にも凡例を書きたいので、1行目のpar関数で引数marを指定し、プロット右側のマージンを8に設定しました1。さらにxpd=TRUEを指定して凡例のボックスがプロット領域でクリップされないようにします。

op <- par(mar=c(5.1,4.1,4.1,8), xpd=T)
items <- c("sample A 12", "sample B")
colors <- c("red", "blue")
boxplot(15:75,30:90,5:35,2:30)
legend("topleft", inset=c(1.01,0), legend=items, fill=colors)
legend("topright", legend=items, fill=colors) 
legend("left", inset=c(1.01,0), legend=items, fill=colors)
legend("right", legend=items, fill=colors)
legend("topleft", legend=items, fill=colors)
legend("bottomleft", legend=c("sample A 12345", "sample B"), fill=colors)

par(op)

このスニペットをRのコンソールにコピペして実行すると、
01_console.png
凡例のボックスの幅が項目の長さに応じて自動的に調整されました。これは期待どおりの結果です。
01_result_console.png
次に、上記のスニペットをファイルに保存し、コンソールからsource()関数でこのスクリプトを読み込ませて実行してみましょう。
02_source_command.png
結果は下図のとおり。凡例のボックスの幅が広がって文字列の右側に大きな余白ができています。さらに、プロット領域の外側に配置した凡例はウインドウの右端でクリップされ、ボックスの右側が欠けてしまいました。
02_legend_width_incorrect.png
なぜsource()で実行した場合は凡例のサイズが正しく調整されないのでしょうか?コンソールにコードを直接入力した場合とsource()とで、何か実行のタイミングの違いが影響してそうです。そこで、legend()の呼び出しのタイミングを遅らせて試したところ、問題は解消しました!以下、その方法です。

方法1. プロンプトを表示して処理を一時停止する

最初に試した方法。Rがグラフをプロットする前にプロンプトを表示して処理を一時停止し、Returnキーを押すとグラフが表示されるようにしてみます。プロンプトを表示するには、1行目のpar()の引数にask=TRUEを追加するだけです。

op <- par(mar=c(5.1,4.1,4.1,8), xpd=T, ask=T)

このように修正したスクリプトをsource()から実行してみます。
03_prompt.png
最初ブランクのQuartzウインドウが表示されますが、Returnキーを押すとグラフが表示されます。結果、凡例のボックスは期待どおりのサイズで表示され、コンソールにコードを打ち込んだ場合と同じになりました。
03_legend_delay.png

方法2. legend()の前にSys.sleep()を入れる

グラフをプロットした後、最初のlegend()を呼び出す前にSys.sleep()関数を呼んでRの処理を一時停止します。サンプルのコードでは、boxplot()の直後にSys.sleep()を入れます。

boxplot(15:75,30:90,5:35,2:30)
Sys.sleep(0.5)
legend("topleft", inset=c(1.01,0), legend=items, fill=colors)

この方法でも正しく表示できました(図は省略)。ただし、Sys.sleep()の引数に指定する秒数が短すぎると効果がありません。今回試した環境では、0.1秒では効果がなく、0.2秒以上で正しく表示できました。

参考

  1. マージンの指定順序は、bottom, left, top, right。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?