matplotlibカラーサイクル状態を取得します


89

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

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

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


これは、現在の状態を変更しなくても実行できます。以下の回答を
sancho.sReinstateMonicaCellio19年

回答:


109

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

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

カラーサイクルの設定

簡単に言うと、色/プロパティサイクルは、さまざまな方法で設定できます(たとえばax.set_color_cycle、バージョン<1.5またはax.set_prop_cycler> = 1.5)。見ていたバージョン1.5以上のために、ここで例を、または以前のスタイルここで

基になるイテレータへのアクセス

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

とにかく、反復可能なカラーサイクルはax._get_lines.color_cycleラインとax._get_patches_for_fill.color_cycleパッチ用です。matplotlib> = 1.5では、これはライブラリ使用するようにcycler変更され、iterableがprop_cycler代わりに呼び出され、色だけでなくプロパティの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()

ここに画像の説明を入力してください

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


私は自分の仕事の領域の一般的なプロットタスクを自動化するためにいくつかのより高いレベルの関数を書いています。多くの場合、これらは複数のmatplotlibオブジェクトの描画を伴い、複数のオブジェクトがカラーサイクルで色を共有するようにしたいので、怠惰な気分の場合は必ずしも色の引数を指定する必要はありません。
mwaskom 2012

12
特定のオブジェクトの色を一致させたいだけの場合は、いつでもその色を取得できます。たとえばline, = ax.plot(x, y)、を使用line.get_color()して、以前にプロットされた線の色を取得します。
ジョーキントン2012

3
ax._get_lines.color_cycle1.5ではもう存在しないようですか?
endolith 2016年

6
私は(近)と等価で反復可能だと思うax._get_lines.prop_cyclerあなたのような構文何か持つことができますif 'color' in ax._get_lines._prop_keys:が続くnext(ax._get_lines.prop_cycler)['color']と提案されているものと同等行うためcolor_cycleの答えでは、私は信じています。色だけを繰り返し表示できるかどうかはわかりませんが、もっと詳しく調べる必要があります。
Jリチャード・スネイプ

1
@endolith確かに(そして感謝します)-しかし、私はジョーのすでに非常に良く受け入れられた答えに座ったほうがよいと感じました。彼は月曜日までにそれを置くことにラウンドを取得していない場合-私の代わりに恐ろしい「答えインコメント」であり、適切な答えを貼ります
Jリチャード・スネイプ

25

1.5で機能する方法は次のとおりです。アンダースコアが付加されたメソッドに依存しないため、将来性が期待できます。

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

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


1
2.0.2で動作します。
KevinG 2017

16

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

可能な限り、@ joe-kingtonの回答の下部に示されているより直接的なアプローチを使用してください。以下のよう_get_linesではありません、それは将来的にない下位互換性のある方法で再び変更される可能性がありますAPI-直面。


カラーサイクラーの次の要素を照会すると、サイクラーの状態が変わることをどのように回避しますか?
風まかせ2016年

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:わかりました。これにより、次の色が表示され、nextが呼び出されなかったかのように動作する新しいイテレータが作成されます。これは色の順序を保持するのではなく、次の色の値だけを保持します。それはあなたに任せます。

これにより、次の出力が得られます。プロットの急勾配がインデックスに対応していることに注意してください。たとえば、最初の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

色を回転させる


ありがとう!明確にするために、それはコピーを返すようには見えませんが、実際のサイクルへの参照です。したがって、rainbow.next()を呼び出すと、実際には次のプロットの外観も変更されます。
mwaskom 2012

5

@Andiが上で言ったことに追加したいだけです。以来color_cyclematplotlibの1.5で廃止され、あなたが使用する必要がありますprop_cycler(ただし、アンディのソリューションをax._get_lines.prop_cycler.next()['color'])私のために、このエラーが返されました:

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

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

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


投稿をディスカッション資料としてではなく、回答としてフォーマットしてください(そうでない場合はコメントです)。主なポイントnext(ax._get_lines.prop_cycler)は、それが可能な代替手段であるということです。
umNyobe 2015

@Carson呼び出しがnext(ax._get_lines.prop_cycler)実際にカラーサイクラーの状態を変更することをどのように回避しますか?
風まかせ2016年

それが実際に私がやろうとしていたことです-の状態を変更しprop_cyclerます。この質問に対する受け入れられた回答を読むと、状態prop_cyclerを変更せずに状態にアクセスする方法はないことがわかります。これは反復可能であるためです。
カーソン

あなたが指摘するエラーは、Python 2 / Python3の違いです。これを指摘してくれてありがとう、私はそれに応じて私の答えを編集しました。
アンディ2016年

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']

0

サイクラーを介してループ全体を実行せずに見つけることができる最も簡単な方法はax1.lines[-1].get_color()です。


-1

matplotlibバージョン2.2.3にはget_next_color()_get_linesプロパティに次のメソッドがあります。

import from matplotlib import pyplot as plt
fig, ax = plt.subplots()
next_color = ax._get_lines.get_next_color()

get_next_color() htmlカラー文字列を返し、カラーサイクルイテレータを進めます。


-1

カラー(および完全なスタイル)サイクルにアクセスするにはどうすればよいですか?

現在の状態はに保存されax._get_lines.prop_cyclerます。ジェネリックitertools.cycle、特にax._get_lines.prop_cycler(以下を参照)の「ベースリスト」を公開するための組み込みメソッドはありません。

に関する情報を取得するためのいくつかの関数をここに投稿しましたitertools.cycle。その後、使用することができます

style_cycle = ax._get_lines.prop_cycler
curr_style = get_cycle_state(style_cycle)  # <-- my (non-builtin) function
curr_color = curr_style['color']

サイクルの状態を変更せずに現在の色を取得します


TL; DR

カラー(および完全なスタイル)サイクルはどこに保存されますか?

スタイルサイクルは2つの異なる場所に保存されます。1つはデフォルト用で、もう1つは現在の軸用です(軸ハンドラーであるimport matplotlib.pyplot as pltと仮定ax)。

default_prop_cycler = plt.rcParams['axes.prop_cycle']
current_prop_cycle = ax._get_lines.prop_cycler

これらには異なるクラスがあることに注意してください。デフォルトは「基本サイクル設定」であり、どの軸の現在の状態も認識していませんが、現在は従うサイクルとその現在の状態を認識しています。

print('type(default_prop_cycler) =', type(default_prop_cycler))
print('type(current_prop_cycle) =', type(current_prop_cycle))

[]: type(default_prop_cycler) = <class 'cycler.Cycler'>
[]: type(current_prop_cycle) = <class 'itertools.cycle'>

デフォルトのサイクルには、サイクルするいくつかのキー(プロパティ)があり、1つは色のみを取得できます。

print('default_prop_cycler.keys =', default_prop_cycler.keys)
default_prop_cycler2 = plt.rcParams['axes.prop_cycle'].by_key()
print(default_prop_cycler2)
print('colors =', default_prop_cycler2['color'])

[]: default_prop_cycler.keys = {'color', 'linestyle'}
[]: {'color': ['r', 'g', 'b', 'y'], 'linestyle': ['-', '--', ':', '-.']}
[]: colors = ['r', 'g', 'b', 'y']

一つでも変更される可能性がcycler与えられたために使用するaxesことを定義した後、custom_prop_cyclerで、

ax.set_prop_cycle(custom_prop_cycler)

ただし、ジェネリックitertools.cycle、特にの「ベースリスト」を公開するための組み込みメソッドはありませんax._get_lines.prop_cycler

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.