40

散布図をプロットするには、matplotlib を使用します。

ここに画像の説明を入力

そして、 matplotlibのヒントに従って、透明なボックスを使用してバブルにラベルを付けます。

コードは次のとおりです。

if show_annote:
    for i in range(len(x)):
        annote_text = annotes[i][0][0]  # STK_ID
        ax.annotate(annote_text, xy=(x[i], y[i]), xytext=(-10,3),
            textcoords='offset points', ha='center', va='bottom',
            bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.2),
            fontproperties=ANNOTE_FONT) 

そして結果のプロット: ここに画像の説明を入力

ただし、オーバーラップを減らすにはまだ改善の余地があります (たとえば、ラベル ボックスのオフセットは (-10,3) に固定されています)。次のことができるアルゴリズムはありますか?

  1. 近隣の混み具合に応じて、ラベル ボックスのオフセットを動的に変更する
  2. ラベル ボックスをリモートで動的に配置し、バブルとラベル ボックスの間に矢印線を追加する
  3. ラベルの向きを多少変更する
  4. label_box オーバーラップ バブルは、label_box オーバーラップ label_box よりも優れていますか?

人間の目でグラフを簡単に理解できるようにしたいだけなので、一部の重複は問題ありませ。また、チャート内のバブルの量は、ほとんどの場合 150 未満です。

いわゆるForce-based label placement http://bl.ocks.org/MoritzStefaner/1377729 は非常に興味深いものです。アルゴリズムを実装するために利用できる Python コード/パッケージがあるかどうかはわかりません。

私は学者ではなく、最適な解決策を探していません。私のpythonコードは多くのチャートにラベルを付ける必要があるため、速度/メモリは考慮の範囲内です.

迅速かつ効果的な解決策を探しています。この件に関するヘルプ (コード、アルゴリズム、ヒント、考え) はありますか? ありがとう。

4

4 に答える 4

26

adjustTextこの目的のために特別に作成された私のライブラリを使用する別のオプション( https://github.com/Phlya/adjustText )。

from adjustText import adjust_text
np.random.seed(2016)

N = 50
scatter_data = np.random.rand(N, 3)
fig, ax = plt.subplots()
ax.scatter(scatter_data[:, 0], scatter_data[:, 1],
           c=scatter_data[:, 2], s=scatter_data[:, 2] * 150)
labels = ['ano_{}'.format(i) for i in range(N)]
texts = []
for x, y, text in zip(scatter_data[:, 0], scatter_data[:, 1], labels):
    texts.append(ax.text(x, y, text))
plt.show()

ここに画像の説明を入力

np.random.seed(2016)

N = 50
scatter_data = np.random.rand(N, 3)
fig, ax = plt.subplots()
ax.scatter(scatter_data[:, 0], scatter_data[:, 1],
           c=scatter_data[:, 2], s=scatter_data[:, 2] * 150)
labels = ['ano_{}'.format(i) for i in range(N)]
texts = []
for x, y, text in zip(scatter_data[:, 0], scatter_data[:, 1], labels):
    texts.append(ax.text(x, y, text))
adjust_text(texts, force_text=0.05, arrowprops=dict(arrowstyle="-|>",
                                                    color='r', alpha=0.5))
plt.show()

ここに画像の説明を入力

泡からは反発せず、泡の中心や他のテキストからのみ反発します。

于 2017-01-07T10:08:35.600 に答える
22

エッジの周りは少し荒いです (スプリング ネットワークと反発力の相対的な強さをスケーリングする方法がよくわかりません。また、バウンディング ボックスが少し台無しになっています)。

import networkx as nx

N = 15
scatter_data = rand(3, N)
G=nx.Graph()

data_nodes = []
init_pos = {}
for j, b in enumerate(scatter_data.T):
    x, y, _ = b
    data_str = 'data_{0}'.format(j)
    ano_str = 'ano_{0}'.format(j)
    G.add_node(data_str)
    G.add_node(ano_str)
    G.add_edge(data_str, ano_str)
    data_nodes.append(data_str)
    init_pos[data_str] = (x, y)
    init_pos[ano_str] = (x, y)

pos = nx.spring_layout(G, pos=init_pos, fixed=data_nodes)
ax = gca()
ax.scatter(scatter_data[0], scatter_data[1], c=scatter_data[2], s=scatter_data[2]*150)

for j in range(N):
    data_str = 'data_{0}'.format(j)
    ano_str = 'ano_{0}'.format(j)
    ax.annotate(ano_str,
                xy=pos[data_str], xycoords='data',
                xytext=pos[ano_str], textcoords='data',
                arrowprops=dict(arrowstyle="->",
                                connectionstyle="arc3"))

all_pos = np.vstack(pos.values())
mins = np.min(all_pos, 0)
maxs = np.max(all_pos, 0)

ax.set_xlim([mins[0], maxs[0]])
ax.set_ylim([mins[1], maxs[1]])

draw()

サンプル画像

うまく機能するかどうかは、データがどのようにクラスター化されているかによって少し異なります。

于 2013-04-07T06:35:53.393 に答える