Apakah mungkin untuk menanyakan status saat ini dari siklus warna matplotlib? Dengan kata lain, apakah ada fungsi get_cycle_state
yang akan berperilaku seperti berikut?
>>> plot(x1, y1)
>>> plot(x2, y2)
>>> state = get_cycle_state()
>>> print state
2
Di mana saya mengharapkan status menjadi indeks warna berikutnya yang akan digunakan dalam plot. Atau, jika mengembalikan warna berikutnya ("r" untuk siklus default dalam contoh di atas), itu juga bagus.
python
matplotlib
mwaskom.dll
sumber
sumber
Jawaban:
Mengakses iterator siklus warna
Tidak ada metode "menghadap pengguna" (alias "publik") untuk mengakses iterator yang mendasarinya, tetapi Anda dapat mengaksesnya melalui metode "pribadi" (menurut konvensi). Namun, Anda tidak bisa mendapatkan keadaan
iterator
tanpa mengubahnya.Mengatur siklus warna
Singkatnya: Anda dapat menyetel siklus warna / properti dalam berbagai cara (misalnya
ax.set_color_cycle
dalam versi <1.5 atauax.set_prop_cycler
di> = 1.5). Lihat contoh di sini untuk versi 1.5 atau yang lebih baru , atau gaya sebelumnya di sini .Mengakses iterator yang mendasari
Namun, meskipun tidak ada metode publik untuk mengakses iterable, Anda bisa mengaksesnya untuk objek sumbu tertentu (
ax
) melalui_get_lines
instance kelas helper.ax._get_lines
adalah sentuhan dengan nama yang membingungkan, tetapi mesin di belakang layarlah yang memungkinkanplot
perintah untuk memproses semua cara aneh dan beragam yangplot
dapat dipanggil. Antara lain, itulah yang melacak warna apa yang akan ditetapkan secara otomatis. Demikian pula, adaax._get_patches_for_fill
untuk mengontrol perputaran melalui warna isian default dan properti tambalan.Bagaimanapun, siklus warna yang dapat diulang
ax._get_lines.color_cycle
untuk garis danax._get_patches_for_fill.color_cycle
untuk tambalan. Pada matplotlib> = 1.5, ini telah diubah untuk menggunakancycler
perpustakaan , dan iterable dipanggilprop_cycler
sebagai ganticolor_cycle
dan menghasilkandict
properti alih-alih hanya warna.Secara keseluruhan, Anda akan melakukan sesuatu seperti:
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']
Anda tidak dapat melihat status file
iterator
Namun, objek ini adalah "telanjang"
iterator
. Kita bisa dengan mudah mendapatkan item berikutnya (misalnyanext_color = next(color_cycle)
, tapi itu berarti warna berikutnya setelah itu akan diplot. Secara desain, tidak ada cara untuk mendapatkan status iterator saat ini tanpa mengubahnya.Dalam
v1.5
atau lebih besar, alangkah baiknya untuk mendapatkancycler
objek yang digunakan, karena kita bisa menyimpulkan keadaannya saat ini. Namun,cycler
objek itu sendiri tidak dapat diakses (secara publik atau pribadi) di mana pun. Sebaliknya, hanyaitertools.cycle
instance yang dibuat daricycler
objek yang dapat diakses. Apa pun itu, tidak ada cara untuk mencapai status yang mendasari pengendara sepeda warna / properti.Cocokkan warna item yang sebelumnya diplot
Dalam kasus Anda, sepertinya Anda ingin mencocokkan warna sesuatu yang baru saja diplot. Alih-alih mencoba menentukan warna / propertinya, tetapkan warna / dll dari item baru Anda berdasarkan properti dari apa yang diplot.
Misalnya, dalam kasus yang Anda jelaskan, saya akan melakukan sesuatu seperti ini:
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()
Ini bukan satu-satunya cara, tetapi lebih bersih daripada mencoba mendapatkan warna garis yang diplot sebelumnya, dalam kasus ini.
sumber
line, = ax.plot(x, y)
dan kemudian gunakanline.get_color()
untuk mendapatkan warna dari garis yang telah diplot sebelumnya.ax._get_lines.color_cycle
tidak ada lagi di 1,5?ax._get_lines.prop_cycler
Anda dapat memiliki konstruksi sepertiif 'color' in ax._get_lines._prop_keys:
diikuti olehnext(ax._get_lines.prop_cycler)['color']
untuk melakukan padanan dari apa yang disarankancolor_cycle
dalam jawaban, saya percaya. Saya tidak yakin apakah Anda bisa mendapatkan iterable hanya warna, saya perlu menjelajahi lebih banyak.Berikut adalah cara yang berhasil di 1.5 yang diharapkan akan terbukti di masa depan karena tidak bergantung pada metode yang diawali dengan garis bawah:
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
Ini akan memberi Anda daftar warna yang ditentukan agar gaya saat ini.
sumber
Catatan: Di matplotlib versi terbaru (> = 1.5)
_get_lines
telah berubah. Anda sekarang perlu untuk menggunakannext(ax._get_lines.prop_cycler)['color']
Python 2 atau 3 (atauax._get_lines.prop_cycler.next()['color']
di Python 2 ) untuk mendapatkan warna berikutnya dari siklus warna.Jika memungkinkan, gunakan pendekatan yang lebih langsung yang ditunjukkan di bagian bawah jawaban @ joe-kington. Karena
_get_lines
tidak menghadap API, ini mungkin berubah lagi dengan cara yang tidak kompatibel ke belakang di masa mendatang.sumber
Tentu, ini akan berhasil.
#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,
Memberikan:
<itertools.cycle object at 0x034CB288> r c m y k b g r c m
Berikut adalah fungsi itertools yang digunakan matplotlib itertools.cycle
Sunting: Terima kasih atas komentarnya, tampaknya iterator tidak dapat disalin. Ide akan membuang siklus penuh dan melacak nilai mana yang Anda gunakan, izinkan saya kembali ke sana.
Sunting2: Baiklah, ini akan memberi Anda warna berikutnya dan membuat iterator baru yang berperilaku seolah-olah berikutnya tidak dipanggil. Ini tidak mempertahankan urutan pewarnaan, hanya nilai warna berikutnya, saya serahkan kepada Anda.
Ini memberikan hasil sebagai berikut, perhatikan bahwa kecuraman di plot sesuai dengan indeks, misalnya g pertama adalah grafik paling bawah dan seterusnya.
#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()
Menghibur
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
sumber
Saya hanya ingin menambahkan apa yang dikatakan @Andi di atas. Karena
color_cycle
sudah tidak digunakan lagi di matplotlib 1.5, Anda harus menggunakanprop_cycler
, namun solusi Andi (ax._get_lines.prop_cycler.next()['color']
) mengembalikan kesalahan ini untuk saya:Kode yang berhasil untuk saya adalah
next(ax._get_lines.prop_cycler)
:, yang sebenarnya tidak jauh dari respons asli @ joe-kington.Secara pribadi, saya mengalami masalah ini saat membuat sumbu twinx (), yang mengatur ulang color cycler. Saya membutuhkan cara untuk membuat siklus warna dengan benar karena saya sedang menggunakannya
style.use('ggplot')
. Mungkin ada cara yang lebih mudah / lebih baik untuk melakukan ini, jadi silakan koreksi saya.sumber
next(ax._get_lines.prop_cycler)
adalah alternatif yang memungkinkan.next(ax._get_lines.prop_cycler)
benar-benar mengubah status siklus warna?prop_cycler
. Jika Anda membaca jawaban yang diterima untuk pertanyaan ini, Anda akan melihat bahwa tidak ada cara untuk mengakses statusprop_cycler
tanpa mengubah statusnya karena ini dapat diulang.Karena matplotlib menggunakan,
itertools.cycle
kita sebenarnya dapat melihat seluruh siklus warna dan kemudian mengembalikan iterator ke keadaan sebelumnya: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
Ini harus mengembalikan daftar tanpa mengubah status iterator.
Gunakan dengan matplotlib> = 1.5:
>>> list_from_cycle(ax._get_lines.prop_cycler) [{'color': 'r'}, {'color': 'g'}, {'color': 'b'}]
atau dengan matplotlib <1.5:
>>> list_from_cycle(ax._get_lines.color_cycle) ['r', 'g', 'b']
sumber
Cara paling sederhana yang bisa saya temukan tanpa melakukan seluruh putaran melalui pengendara sepeda adalah
ax1.lines[-1].get_color()
.sumber
Di matplotlib versi 2.2.3 ada
get_next_color()
metode di_get_lines
properti:import from matplotlib import pyplot as plt fig, ax = plt.subplots() next_color = ax._get_lines.get_next_color()
get_next_color()
mengembalikan string warna html, dan memajukan iterator siklus warna.sumber
Bagaimana cara mengakses siklus warna (dan gaya lengkap)?
Status saat ini disimpan di
ax._get_lines.prop_cycler
. Tidak ada metode bawaan untuk mengekspos "daftar dasar" untuk generikitertools.cycle
, dan khususnya untukax._get_lines.prop_cycler
(lihat di bawah).Saya telah memposting di sini beberapa fungsi untuk mendapatkan info tentang a
itertools.cycle
. Seseorang kemudian bisa menggunakanstyle_cycle = ax._get_lines.prop_cycler curr_style = get_cycle_state(style_cycle) # <-- my (non-builtin) function curr_color = curr_style['color']
untuk mendapatkan warna saat ini tanpa mengubah status siklus .
TL; DR
Di mana siklus warna (dan gaya lengkap) disimpan?
Siklus gaya disimpan di dua tempat berbeda, satu untuk default , dan satu lagi untuk sumbu saat ini (dengan asumsi
import matplotlib.pyplot as plt
danax
merupakan pengendali sumbu):default_prop_cycler = plt.rcParams['axes.prop_cycle'] current_prop_cycle = ax._get_lines.prop_cycler
Perhatikan bahwa ini memiliki kelas yang berbeda. Standarnya adalah "setelan siklus dasar" dan tidak mengetahui status saat ini untuk sumbu mana pun, sedangkan arus mengetahui siklus yang akan diikuti dan statusnya saat ini:
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'>
Siklus default mungkin memiliki beberapa kunci (properti) untuk diputar, dan seseorang hanya bisa mendapatkan warna:
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']
Seseorang bahkan bisa mengubah
cycler
to use for a givenaxes
, setelah mendefinisikannyacustom_prop_cycler
, denganTetapi tidak ada metode built-in untuk mengekspos "daftar dasar" untuk generik
itertools.cycle
, dan khususnya untukax._get_lines.prop_cycler
.sumber