96

matplotlib カラー サイクルの現在の状態を照会することは可能ですか? get_cycle_stateつまり、次のように動作する関数はありますか?

>>> plot(x1, y1)
>>> plot(x2, y2)
>>> state = get_cycle_state()
>>> print state
2

状態は、プロットで使用される次の色のインデックスになると予想されます。または、次の色 (上記の例のデフォルト サイクルの "r") が返された場合、それも問題ありません。

4

10 に答える 10

120

カラー サイクル イテレータへのアクセス

基礎となる反復子にアクセスするための「ユーザー向け」(別名「パブリック」) メソッドはありませんが、「プライベート」(慣例により) メソッドを介してアクセスできます。ただし、変更せずに の状態を取得することはできませんiterator

カラーサイクルの設定

余談ですが、さまざまな方法で色/プロパティ サイクルを設定できます (たとえばax.set_color_cycle、バージョン <1.5 またはax.set_prop_cycler>=1.5)。バージョン 1.5 以降についてはこちらの、または以前のスタイルについてはこちらをご覧ください。

基礎となる反復子へのアクセス

ただし、 iterable にアクセスする公開メソッドはありませんが、ヘルパー クラス インスタンス axを介して特定の軸オブジェクト ( )にアクセスできます。やや紛らわしい名前ですが、呼び出される可能性のある奇妙でさまざまな方法のすべてをコマンドが処理できるようにするのは、舞台裏の機構です。とりわけ、どの色を自動的に割り当てるかを追跡します。同様に、デフォルトの塗りつぶしの色とパッチのプロパティの循環を制御する必要があります。_get_linesax._get_linesplotplotax._get_patches_for_fill

いずれにせよ、反復可能なカラー サイクルはax._get_lines.color_cycleラインとax._get_patches_for_fill.color_cycleパッチ用です。matplotlib >=1.5 では、これはlibraryを使用するようcyclerprop_cyclerに変更され、代わりにiterable が呼び出され、色だけではなく of プロパティcolor_cycleが生成されます。dict

全体として、次のようにします。

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
color_cycle = ax._get_lines.color_cycle
# or ax._get_lines.prop_cycler on version >= 1.5
# Note that prop_cycler cycles over dicts, so you'll want next(cycle)['color']

の状態を表示することはできませんiterator

ただし、このオブジェクトは「裸」iteratorです。次のアイテムを簡単に取得できます (たとえば、これは、その後next_color = next(color_cycle)の次の色がプロットされることを意味します。設計上、イテレータの現在の状態を変更せずに取得する方法はありません。

以上の場合、現在の状態を推測できるため、使用されているオブジェクトv1.5を取得すると便利です。cyclerただし、cyclerオブジェクト自体は (公開または非公開で) どこからでもアクセスできません。代わりに、オブジェクトitertools.cycleから作成されたインスタンスのみにアクセスできます。cyclerいずれにせよ、カラー/プロパティ サイクラーの基本的な状態に到達する方法はありません。

代わりに、以前にプロットされたアイテムの色を一致させます

あなたの場合、ちょうどプロットされたものの色を一致させたいと思っているようです。色/プロパティがどうなるかを決定しようとする代わりに、プロットされたもののプロパティに基づいて新しいアイテムの色/その他を設定します。

たとえば、あなたが説明した場合、私は次のようにします:

import matplotlib.pyplot as plt
import numpy as np

def custom_plot(x, y, **kwargs):
    ax = kwargs.pop('ax', plt.gca())
    base_line, = ax.plot(x, y, **kwargs)
    ax.fill_between(x, 0.9*y, 1.1*y, facecolor=base_line.get_color(), alpha=0.5)

x = np.linspace(0, 1, 10)
custom_plot(x, x)
custom_plot(x, 2*x)
custom_plot(x, -x, color='yellow', lw=3)

plt.show()

ここに画像の説明を入力

これが唯一の方法ではありませんが、この場合、事前にプロットされた線の色を取得しようとするよりもクリーンです。

于 2012-12-12T02:24:48.283 に答える
30

1.5 で機能する方法を次に示します。これは、アンダースコアが先頭に追加されたメソッドに依存しないため、将来的に保証されることが期待されます。

colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]

これにより、現在のスタイルの順序で定義された色のリストが表示されます。

于 2016-07-23T06:47:35.213 に答える
18

注: matplotlib の最新バージョン (>= 1.5)_get_linesでは変更されています。色サイクルから次の色を取得するにはnext(ax._get_lines.prop_cycler)['color']、Python 2 または 3 (またはPython 2ax._get_lines.prop_cycler.next()['color'] )でを使用する必要があります。

可能な限り、@ joe-kingtonの回答の下部に示されているより直接的なアプローチを使用してください。_get_linesAPI 向けではないため、将来、後方互換性を持たない方法で再び変更される可能性があります。

于 2015-11-09T11:56:30.150 に答える
6

確かに、これで済みます。

#rainbow

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0,2*np.pi)
ax= plt.subplot(1,1,1)
ax.plot(np.sin(x))
ax.plot(np.cos(x))

rainbow = ax._get_lines.color_cycle
print rainbow
for i, color in enumerate(rainbow):
    if i<10:
        print color,

与えます:

<itertools.cycle object at 0x034CB288>
r c m y k b g r c m

これは、matplotlib が itertools.cycle を使用する itertools 関数です

編集:コメントありがとうございます。イテレータをコピーすることはできないようです。アイデアは、完全なサイクルをダンプして、使用している値を追跡することです。それに戻りましょう。

Edit2: わかりました。これにより、次の色が得られ、次が呼び出されなかったかのように動作する新しい反復子が作成されます。これは色付けの順序を保持しません。次の色の値だけです。それはあなたに任せます。

これにより、次の出力が得られます。プロットの勾配がインデックスに対応していることに注意してください。たとえば、最初の g は最も下のグラフなどです。

#rainbow

import matplotlib.pyplot as plt
import numpy as np
import collections
import itertools

x = np.linspace(0,2*np.pi)
ax= plt.subplot(1,1,1)


def create_rainbow():
    rainbow = [ax._get_lines.color_cycle.next()]
    while True:
        nextval = ax._get_lines.color_cycle.next()
        if nextval not in rainbow:
            rainbow.append(nextval)
        else:
            return rainbow

def next_color(axis_handle=ax):
    rainbow = create_rainbow()
    double_rainbow = collections.deque(rainbow)
    nextval = ax._get_lines.color_cycle.next()
    double_rainbow.rotate(-1)
    return nextval, itertools.cycle(double_rainbow)


for i in range(1,10):
    nextval, ax._get_lines.color_cycle = next_color(ax)
    print "Next color is: ", nextval
    ax.plot(i*(x))


plt.savefig("SO_rotate_color.png")
plt.show()

コンソール

Next color is:  g
Next color is:  c
Next color is:  y
Next color is:  b
Next color is:  r
Next color is:  m
Next color is:  k
Next color is:  g
Next color is:  c

色を回転

于 2012-12-12T02:20:38.827 に答える
5

@Andiが上で言ったことに追加したいだけです。color_cycleは matplotlib 1.5 で非推奨になっているため、 を使用する必要がありますが、prop_cyclerAndi のソリューション ( ax._get_lines.prop_cycler.next()['color']) は次のエラーを返しました。

AttributeError: 'itertools.cycle' オブジェクトに属性 'next' がありません

私のために働いたコードは:next(ax._get_lines.prop_cycler)で、実際には @joe-kington の元の応答からそれほど離れていません。

個人的には、カラー サイクラーをリセットする twinx() 軸を作成しているときに、この問題に遭遇しました。を使用していたため、色を正しく循環させる方法が必要でしたstyle.use('ggplot')。これを行うためのより簡単な/より良い方法があるかもしれませんので、お気軽に修正してください。

于 2015-12-15T17:20:45.030 に答える
1

matplotlib が使用itertools.cycleするため、実際にカラー サイクル全体を調べてから、イテレータを以前の状態に復元できます。

def list_from_cycle(cycle):
    first = next(cycle)
    result = [first]
    for current in cycle:
        if current == first:
            break
        result.append(current)

    # Reset iterator state:
    for current in cycle:
        if current == result[-1]:
            break
    return result

これは、イテレータの状態を変更せずにリストを返す必要があります。

matplotlib >= 1.5 で使用します。

>>> list_from_cycle(ax._get_lines.prop_cycler)
[{'color': 'r'}, {'color': 'g'}, {'color': 'b'}]

または matplotlib < 1.5 の場合:

>>> list_from_cycle(ax._get_lines.color_cycle)
['r', 'g', 'b']
于 2016-09-22T08:38:25.553 に答える