Matplotlib のオーバーラップするアノテーション / テキスト
質問
グラフで注釈テキストが重ならないようにしようとしています。の回答で提案された方法は Matplotlibのオーバーラップする注釈 は非常に有望に見えますが、しかし、棒グラフのためのものです。私は"axis"メソッドを私がやりたいことに変換するのに苦労しており、テキストがどのように並んでいるのか理解できません。
import sys
import matplotlib.pyplot as plt
# start new plot
plt.clf()
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
together = [(0, 1.0, 0.4), (25, 1.0127692669427917, 0.41), (50, 1.016404709797609, 0.41), (75, 1.1043426359673716, 0.42), (100, 1.1610446924342996, 0.44), (125, 1.1685687930691457, 0.43), (150, 1.3486407784550272, 0.45), (250, 1.4013999168008104, 0.45)]
together.sort()
for x,y,z in together:
plt.annotate(str(x), xy=(y, z), size=8)
eucs = [y for (x,y,z) in together]
covers = [z for (x,y,z) in together]
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
plt.savefig("test.png")
画像は(これがうまくいけば) ここで (このコード) にあります。
そして ここで (もっと複雑)です。
どのように解決するのですか?
このようなことを実装するために書いた小さなライブラリをここに掲載したいと思います。 https://github.com/Phlya/adjustText 処理の例はこちらで見ることができます。
以下は画像例です。
import matplotlib.pyplot as plt
from adjustText import adjust_text
import numpy as np
together = [(0, 1.0, 0.4), (25, 1.0127692669427917, 0.41), (50, 1.016404709797609, 0.41), (75, 1.1043426359673716, 0.42), (100, 1.1610446924342996, 0.44), (125, 1.1685687930691457, 0.43), (150, 1.3486407784550272, 0.45), (250, 1.4013999168008104, 0.45)]
together.sort()
text = [x for (x,y,z) in together]
eucs = [y for (x,y,z) in together]
covers = [z for (x,y,z) in together]
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, only_move={'points':'y', 'texts':'y'}, arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
もし、完璧な図を作りたいのであれば、少しいじくりまわすことができます。まず、テキストが線に反発するようにしましょう。そのためには、scipy.interpolate.interp1dを使って、線に沿ってたくさんの仮想点を作成するだけです。
ラベルをX軸に沿って移動させないようにしたいのですが、なぜかというと、説明のために移動させないようにするためです。そのために、パラメータ
only_move={'points':'y', 'text':'y'}
. もしラベルがテキストと重なる場合のみx軸に沿って移動させたい場合は
move_only={'points':'y', 'text':'xy'}
. また、この関数は、初めにテキストの元の位置に対する最適な配置を選択するので、y軸方向にもそれが起こるようにしたい場合は、そのように
autoalign='y'
. また、人為的に線を避けたためにテキストが遠くに飛んでいってしまうのを避けるため、点からの反発力を弱めています。すべて一緒です。
from scipy import interpolate
p1 = plt.plot(eucs,covers,color="black", alpha=0.5)
texts = []
for x, y, s in zip(eucs, covers, text):
texts.append(plt.text(x, y, s))
f = interpolate.interp1d(eucs, covers)
x = np.arange(min(eucs), max(eucs), 0.0005)
y = f(x)
plt.xlabel("Proportional Euclidean Distance")
plt.ylabel("Percentage Timewindows Attended")
plt.title("Test plot")
adjust_text(texts, x=x, y=y, autoalign='y',
only_move={'points':'y', 'text':'y'}, force_points=0.15,
arrowprops=dict(arrowstyle="->", color='r', lw=0.5))
plt.show()
関連
-
[解決済み] Matplotlibでプロットを表示するのではなく、画像ファイルに保存する。
-
[解決済み] IPythonノートブックmatplotlibプロットをインラインで行う方法
-
[解決済み】Matplotlibで図のタイトルと軸ラベルのフォントサイズを設定するには?
-
[解決済み] pandasのDataFrameから空のセルを含む行を削除する
-
[解決済み] Pythonのインスタンス変数とクラス変数
-
[解決済み] Pythonによる一対のクロスプロダクト [重複] (英語)
-
[解決済み] Flaskで非同期タスクを作る
-
[解決済み] Python Empty Generator 関数
-
[解決済み] PySparkでデータフレームのカラムをString型からDouble型に変更する方法は?
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pythonのマルチプロセッシングプールimap_unorderedの呼び出しの進捗を表示しますか?
-
[解決済み] Django のテストデータベースをメモリ上だけで動作させるには?
-
[解決済み] 小数点以下1桁を取得する[重複]。
-
[解決済み] タプルのリストを複数のリストに変換するには?
-
[解決済み] Pandasの'Freq'タグにはどのような値が有効ですか?
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] 文字列から先頭と末尾のスペースを削除するには?
-
[解決済み] 値で列挙名を取得する [重複]。
-
[解決済み] djangoフレームワークでフォームフィールドから値を取得するには?
-
[解決済み] matplotlib でプロットの軸、目盛、ラベルの色を変更する方法