matplotlibカラーサイクルの現在の状態を照会することは可能ですか?つまりget_cycle_state
、次のように動作する関数はありますか?
>>> plot(x1, y1)
>>> plot(x2, y2)
>>> state = get_cycle_state()
>>> print state
2
状態は、プロットで使用される次の色のインデックスになると思います。または、次の色(上記の例のデフォルトサイクルでは「r」)が返される場合は、それでも問題ありません。
matplotlibカラーサイクルの現在の状態を照会することは可能ですか?つまりget_cycle_state
、次のように動作する関数はありますか?
>>> plot(x1, y1)
>>> plot(x2, y2)
>>> state = get_cycle_state()
>>> print state
2
状態は、プロットで使用される次の色のインデックスになると思います。または、次の色(上記の例のデフォルトサイクルでは「r」)が返される場合は、それでも問題ありません。
回答:
基になるイテレータにアクセスするための「ユーザー向け」(別名「パブリック」)メソッドはありませんが、「プライベート」(慣例により)メソッドを介してアクセスできます。ただし、を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()
これが唯一の方法ではありませんが、この場合、プロットされた線の色を事前に取得しようとするよりもクリーンです。
line, = ax.plot(x, y)
、を使用line.get_color()
して、以前にプロットされた線の色を取得します。
ax._get_lines.color_cycle
1.5ではもう存在しないようですか?
ax._get_lines.prop_cycler
あなたのような構文何か持つことができますif 'color' in ax._get_lines._prop_keys:
が続くnext(ax._get_lines.prop_cycler)['color']
と提案されているものと同等行うためcolor_cycle
の答えでは、私は信じています。色だけを繰り返し表示できるかどうかはわかりませんが、もっと詳しく調べる必要があります。
1.5で機能する方法は次のとおりです。アンダースコアが付加されたメソッドに依存しないため、将来性が期待できます。
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
これにより、現在のスタイル用に定義された色のリストが表示されます。
注:最新バージョンの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-直面。
確かに、これはそれを行います。
#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
@Andiが上で言ったことに追加したいだけです。以来color_cycle
matplotlibの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)
は、それが可能な代替手段であるということです。
next(ax._get_lines.prop_cycler)
実際にカラーサイクラーの状態を変更することをどのように回避しますか?
prop_cycler
ます。この質問に対する受け入れられた回答を読むと、状態prop_cycler
を変更せずに状態にアクセスする方法はないことがわかります。これは反復可能であるためです。
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']
サイクラーを介してループ全体を実行せずに見つけることができる最も簡単な方法はax1.lines[-1].get_color()
です。
カラー(および完全なスタイル)サイクルにアクセスするにはどうすればよいですか?
現在の状態はに保存され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
。