2012-01-31 24 views
24

matplotlib:散布図上のポイントに注釈を付ける方法は、自動的に配置された矢印ですか?私はmatplotlibので散布図作る場合

plt.scatter(randn(100),randn(100)) 
# set x, y lims 
plt.xlim([...]) 
plt.ylim([...]) 

を私はそれを指す矢印とラベルを与えられた点(x, y)に注釈を付けたいと思います。私はannotateでこれを行うことができると知っていますが、矢印とラベルができない場合(現在の軸のスケール/リミットを考慮して)、矢印とそのラベルを "最適に"配置することをお勧めします他の点と重複する。たとえば、アウトライアポイントにラベルを付ける場合などです。これを行う方法はありますか?完璧である必要はなく、矢印/ラベルをインテリジェントに配置するだけで、ラベル付けされる点の座標は(x,y)となります。ありがとう。

+6

「scatter」は、あなたがやっていることを意図したものではありません。マーカの色やサイズを変えて3次元または4次元のデータをプロットする場合に使用します。ポイントを求めたいときには使用しないでください。本来はポイントに使うのは間違っていませんが、 'plot'が返すLine2Dオブジェクトよりも扱いが複雑なコレクションを返します。 –

答えて

33

基本的には、ありません。

マップラベルの配置を処理するレイアウトエンジンは、驚くほど複雑で、matplotlibの範囲を超えています。 (境界ボックスの交点は、実際にラベルを配置する場所を決定するには多少悪い方法ですが、1000のうち1つのケースでのみ機能するようなコードを作成するのは何ですか? matplotlibが行う複雑なテキストレンダリングの量(例えばラテックス)は、完全にレンダリングすることなくテキストの範囲を決定することは不可能です(むしろ遅い)。

しかし、多くの場合、注釈付きのラベルの背後にある透明なボックスを使用するのが適切な回避策であることがわかります。

など。

import numpy as np 
import matplotlib.pyplot as plt 

np.random.seed(1) 
x, y = np.random.random((2,500)) 

fig, ax = plt.subplots() 
ax.plot(x, y, 'bo') 

# The key option here is `bbox`. I'm just going a bit crazy with it. 
ax.annotate('Something', xy=(x[0], y[0]), xytext=(-20,20), 
      textcoords='offset points', ha='center', va='bottom', 
      bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3), 
      arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0.5', 
          color='red')) 

plt.show() 

enter image description here

+2

私はあなたの例が好きです。また、注釈をフレームの外に置くこともできます。例えば、 'textcoords'のために" axes fraction "を使用します。配置の自動性は、アノテーションを作成する小さなメソッドにラップすることができます。ポイントがボトムの中心に最も近い場合は、それをx軸の下に置きます。それが右端に近い場合は、それを置いてください。自動的に回転さえさえしていても... ...それでも、目印のラベルを隠したり、図の端などで切り取ったりする可能性があるため、 ... – Yann

+0

@Joe:どのような値を 'xytext'(この場合は'(-20,20) ')に与えるのですか? – user248237dfsf

+1

@ user248273 - それはポイントのオフセットです。それは任意ですが、データの範囲に依存することはありません。 kwarg 'textcoords = 'offset points'に注意してください。 'textcoords'のためのさまざまな他の値を渡すことは' xytext'の数字がどのように解釈されるかを制御します。 –

2

使用adjustText(フル開示、私はそれを書きました)。

最初の10ポイントにラベルを付けましょう。私が変更した唯一のパラメータは、ポイントからの反発力を低下させることでした。その数が非常に多く、アルゴリズムを少し時間をかけて注釈をより慎重に配置したいからです。

import numpy as np 
import matplotlib.pyplot as plt 
from adjustText import adjust_text 
np.random.seed(1) 
x, y = np.random.random((2,500)) 

fig, ax = plt.subplots() 
ax.plot(x, y, 'bo') 
ts = [] 
for i in range(10): 
    ts.append(plt.text(x[i], y[i], 'Something'+str(i))) 
adjust_text(ts, x=x, y=y, force_points=0.1, arrowprops=dict(arrowstyle='->', 
color='red')) 
plt.show() 

enter image description here それは理想的ではないですが、ポイントは、ここでは実際に密集していると、時々それらのいずれかを重複することなくそのターゲットに近いテキストを配置する方法はありません。しかし、それはすべて自動で使いやすく、またラベルがお互いに重なり合うこともありません。

PS バウンディングボックスの交差を使用しますが、むしろうまくいきます。