9

本質的には次のようなコードで散布図を作成します

cmap = (matplotlib.color.LinearSegmentedColormap.
        from_list('blueWhiteRed', ['blue', 'white', 'red']))

fig = matplotlib.figure.Figure(figsize=(4, 4), dpi=72)
ax = fig.gca()

for record in data:
    level = record.level # a float in [0.0, 1.0]
    marker = record.marker # one of 'o', 's', '^', '*', etc.
    ax.scatter(record.x, record.y, marker=marker,
               c=level, vmin=0, vmax=1, cmap=cmap, **otherkwargs)

# various settings of ticks, labels, etc. omitted

canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)
fig.set_canvas(canvas)
canvas.print_png('/path/to/output/fig.png')

私の質問はこれです:

cmapプロットの右端に沿って垂直カラーバー ( のカラーマップを表す) を取得するには、上記のコードに何を追加する必要がありますか?

: Matplotlib はまったく理解できないと思います。これは、その設計とドキュメントの両方に当てはまります。(試行錯誤ではありません。私は多くの時間、労力、さらにはいくらかのお金を費やしてきました。) したがって、完全で機能するコード (たとえそれが単なるおもちゃの例であっても) に感謝します。省略された詳細を埋めたり、コードのバグを修正したりすることはできません。


編集: 上記の「コード スケッチ」の重要な欠落、つまり への各呼び出しでのレコード固有のマーカー指定を修正しましたax.scatter。これが、 への複数の呼び出しで散布図を作成する理由ですax.scatterが、確かに、使用される maker shape ごとに scatter への呼び出しの数を少なくとも 1 つに減らすことができます。例えば

for marker in set(record.marker for record in data):
    X, Y, COLOR = zip(*((record.x, record.y, record.level)
                        for record in data if record.marker == marker))
    ax.scatter(X, Y, marker=marker,
               c=COLOR, vmin=0, vmax=1, cmap=cmap,
               **otherkwargs)

次のように、同じトリックを拡張して、すべての呼び出しをax.scatter1 つにまとめようとしました (一連のマーカーをmarker引数として渡すことにより)。

X, Y, COLOR, MARKER = zip(*((record.x, record.y, record.level, record.marker)
                            for record in data))

ax.scatter(X, Y, marker=MARKER,
           c=COLOR, vmin=0, vmax=1, cmap=cmap,
           **otherkwargs)

...しかし、これは失敗します。エラーは次のようになります (いくつかの長いパスを削除した後):

Traceback (most recent call last):
  File "src/demo.py", line 222, in <module>
    main()
  File "src/demo.py", line 91, in main
    **otherkwargs)
  File "<abbreviated-path>/matplotlib/axes.py", line 6100, in scatter
    marker_obj = mmarkers.MarkerStyle(marker)
  File "<abbreviated-path>/matplotlib/markers.py", line 113, in __init__
    self.set_marker(marker)
  File "<abbreviated-path>/matplotlib/markers.py", line 179, in set_marker
    raise ValueError('Unrecognized marker style {}'.format(marker))
ValueError: Unrecognized marker style ('^', 'o', '^', '*', 'o', 's', 'o', 'o', '^', 's', 'o', 'o', '^', '^', '*', 'o', '*', '*', 's', 's', 'o', 's', 'o', '^', 'o', 'o', '*', '^', 's', '^', '^', 's', '*')

AFAICT、tcaswell のレシピでは、呼び出しを 1 つに減らす必要がありax.scatterますが、この要件は、同じ散布図内の複数のマーカー形状に対する私の絶対要件と競合するようです。

4

4 に答える 4

12

セットごとに異なるマーカーを使用する必要がある場合は、少し余分な作業を行い、すべてを同じにする必要があります (それ以外の場合は、デフォルトで散布図ごとclimsのデータの最小/最大からスケーリングされます)。c

from pylab import *
import matplotlib.lines as mlines
import itertools
fig = gcf()
ax = fig.gca()

# make some temorary arrays
X = []
Y = []
C = []
cb = None
# generate fake data
markers = ['','o','*','^','v']
cmin = 0
cmax = 1
for record,marker in itertools.izip(range(5),itertools.cycle(mlines.Line2D.filled_markers)):
    x = rand(50)
    y = rand(50)
    c = rand(1)[0] * np.ones(x.shape)
    if cb is None:
        s = ax.scatter(x,y,c=c,marker=markers[record],linewidths=0)
        s.set_clim([cmin,cmax])
        cb = fig.colorbar(s)
    else:
        s = ax.scatter(x,y,c=c,marker=markers[record],linewidths=0)
        s.set_clim([cmin,cmax])

cb.set_label('Cbar Label Here')

形状のlinewidths=0境界線の幅を設定します。小さな形状の場合、黒い境界線が塗りつぶしの色を圧倒する可能性があることがわかりました。

色付き散布図

1 つの形状のみが必要な場合は、単一の散布図でこれをすべて行うことができます。ループを通過するパスごとに個別の形状を作成する必要はありません。

from pylab import *
fig = gcf()
ax = fig.gca()

# make some temorary arrays
X = []
Y = []
C = []
# generate fake data
for record in range(5):
    x = rand(50)
    y = rand(50)
    c = rand(1)[0] * np.ones(x.shape)
    print c
    X.append(x)
    Y.append(y)
    C.append(c)

X = np.hstack(X)
Y = np.hstack(Y)
C = np.hstack(C)

データをすべて 1D 配列にまとめたら、散布図を作成し、戻り値を保持します。

s = ax.scatter(X,Y,c=C)

次に、カラー バーを作成し、返されたオブジェクトをscatter最初の引数として渡します。

cb = plt.colorbar(s)
cb.set_label('Cbar Label Here')

これを行う必要があるのは、使用するカラー マップ (マップと範囲の両方) をカラー バーが認識できるようにするためです。

ここに画像の説明を入力

于 2012-12-19T05:21:57.727 に答える
7

あなたの最善の策は、データをパンダのデータフレームに詰め込み、次のようにすべてのマーカーをループすることだと思います。

import numpy as np    
import pandas as pd
import matplotlib.pyplot as plt

markers = ['s', 'o', '^']
records = []
for n in range(37):
    records.append([np.random.normal(), np.random.normal(), np.random.normal(), 
                    markers[np.random.randint(0, high=3)]])

records = pd.DataFrame(records, columns=['x', 'y', 'z', 'marker'])

fig, ax = plt.subplots()
for m in np.unique(records.marker):
    selector = records.marker == m
    s = ax.scatter(records[selector].x, records[selector].y, c=records[selector].z,
                   marker=m, cmap=plt.cm.coolwarm, 
                   vmin=records.z.min(), vmax=records.z.max())

cbar = plt.colorbar(mappable=s, ax=ax)
cbar.set_label('My Label')

結果グラフ

于 2012-12-21T01:59:50.330 に答える
1

これでうまくいくはずだと思います。しばらく前にmatplotlibクックブックの例の1つからこれを取得したと確信していますが、今は見つけられないようです...

from mpl_toolkits.axes_grid1 import make_axes_locatable

cmap = (matplotlib.color.LinearSegmentedColormap.
        from_list('blueWhiteRed', ['blue', 'white', 'red']))

fig = matplotlib.figure.Figure(figsize=(4, 4), dpi=72)
ax = fig.gca()

for record in data:
    level = record.level # a float in [0.0, 1.0]
    ax.scatter(record.x, record.y,
               c=level, vmin=0, vmax=1, cmap=cmap, **otherkwargs)

# various settings of ticks, labels, etc. omitted

divider= make_axes_locatable(ax)
cax = divider.append_axes("right", size="1%", pad=0.05)
cb = plt.colorbar(cax=cax)
cb.set_label('Cbar Label Here')

canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)
fig.set_canvas(canvas)
canvas.print_png('/path/to/output/fig.png')
于 2012-12-19T02:44:04.620 に答える