Matplotlib रंग चक्र अवस्था प्राप्त करें


89

क्या मैटप्लोटलिब रंग चक्र की वर्तमान स्थिति को क्वेरी करना संभव है? दूसरे शब्दों में एक फ़ंक्शन है get_cycle_stateजो निम्न तरीके से व्यवहार करेगा?

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

जहां मुझे उम्मीद है कि राज्य अगले रंग का सूचकांक होगा जो एक प्लॉट में इस्तेमाल किया जाएगा। वैकल्पिक रूप से, अगर यह अगले रंग (ऊपर के उदाहरण में डिफ़ॉल्ट चक्र के लिए "r") लौटा, तो यह भी ठीक होगा।


यह किया जा सकता है, यहां तक ​​कि वर्तमान स्थिति को बदलने के बिना, नीचे जवाब देखें
sancho.s ReinstateMonicaCellio

जवाबों:


107

रंग चक्र पुनरावृत्ति तक पहुँचना

अंतर्निहित पुनरावृत्ति तक पहुंचने के लिए कोई "उपयोगकर्ता-सामना" (उर्फ "सार्वजनिक") विधि नहीं है, लेकिन आप इसे "निजी" (सम्मेलन द्वारा) तरीकों से एक्सेस कर सकते हैं। हालाँकि, आप iteratorइसे बदले बिना राज्य नहीं प्राप्त कर सकते ।

रंग चक्र सेट करना

एक तरफ त्वरित: आप विभिन्न तरीकों से रंग / संपत्ति चक्र सेट कर सकते हैं (उदाहरण ax.set_color_cycleके लिए संस्करण <1.5 या ax.set_prop_cycler> = 1.5)। संस्करण 1.5 या अधिक , या पिछली शैली के लिए यहाँ उदाहरण देखें

अंतर्निहित पुनरावृत्ति तक पहुँचना

हालाँकि, जब चलने-फिरने के लिए कोई सार्वजनिक-सामना करने की कोई विधि नहीं है, तो आप इसे सहायक वर्ग के उदाहरण के axमाध्यम से किसी दिए गए अक्ष ऑब्जेक्ट ( ) के लिए एक्सेस कर सकते हैं _get_linesax._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 करने के लिए बदल गया है , और चलने योग्य को 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()

यहाँ छवि विवरण दर्ज करें

यह एकमात्र तरीका नहीं है, लेकिन इस मामले में, पहले से तैयार की गई रेखा का रंग प्राप्त करने की कोशिश करने की तुलना में इसका क्लीनर।


मैं अपने काम के क्षेत्र के लिए सामान्य प्लॉटिंग कार्यों को स्वचालित करने के लिए कुछ उच्च-स्तरीय फ़ंक्शन लिख रहा हूं। अक्सर ये कई मैटप्लोटलिब वस्तुओं को आकर्षित करते हैं, और मैं चाहूंगा कि कई वस्तुएं रंग चक्र में एक रंग साझा करें, इसलिए मुझे आलसी महसूस होने पर मुझे हमेशा एक रंग तर्क प्रदान करने की आवश्यकता नहीं है।
mwaskom

12
यदि आप किसी विशेष वस्तु के रंग से मेल खाना चाहते हैं, तो आप हमेशा उसका रंग पकड़ सकते हैं। जैसे line, = ax.plot(x, y)और फिर line.get_color()पहले से तैयार लाइन का रंग पाने के लिए उपयोग करें।
जो किंग्सटन

3
ऐसा लगता है कि ax._get_lines.color_cycleअब 1.5 में मौजूद नहीं है?
एंडोलिथ

6
मुझे लगता है कि (निकट) समतुल्य एक पुनरावृत्ति है, ax._get_lines.prop_cyclerआप एक निर्माण कर सकते हैं जैसे कि उत्तर में जो सुझाव दिया गया है उसके बराबर करने के लिए if 'color' in ax._get_lines._prop_keys:उसके बाद कुछ next(ax._get_lines.prop_cycler)['color']ऐसा हो color_cycleसकता है, मुझे विश्वास है। मुझे यकीन नहीं है कि क्या आप सिर्फ रंगों का पुनरावृत्ति प्राप्त कर सकते हैं, मुझे और अधिक जानकारी प्राप्त करने की आवश्यकता है।
जे रिचर्ड स्नेप

1
@endolith ज़रूर (और धन्यवाद) - लेकिन मुझे लगा कि यह जो पहले से ही बहुत अच्छा और स्वीकृत जवाब है, में बैठना बेहतर होगा। यदि वह सोमवार तक इसे लगाने के लिए चक्कर नहीं लगाता है - तो मैं "जवाब-इन-कमेंट्स" के बजाय एक उचित जवाब दूंगा
जे रिचर्ड स्नेप

25

यहां एक तरीका है जो 1.5 में काम करता है जो उम्मीद के मुताबिक भविष्य का सबूत होगा क्योंकि यह अंडरस्कोर के साथ पहले से तय किए गए तरीकों पर भरोसा नहीं करता है:

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

यह आपको वर्तमान शैली के लिए परिभाषित रंगों की एक सूची देगा।


1
2.0.2 में काम करता है।
KevinG

16

नोट: नवीनतम संस्करण में matplotlib (> = 1.5) _get_linesबदल गया है। अब आप उपयोग करने की आवश्यकता next(ax._get_lines.prop_cycler)['color']अजगर 2 या 3 (या में ax._get_lines.prop_cycler.next()['color']में अजगर 2 ) रंग चक्र से अगले रंग मिलता है।

जहाँ भी संभव हो @ जो-किंग्टन के उत्तर के निचले भाग में दिखाए गए अधिक प्रत्यक्ष दृष्टिकोण का उपयोग करें। जैसा कि _get_linesएपीआई का सामना नहीं कर रहा है यह भविष्य में एक नहीं पिछड़े संगत तरीके से फिर से बदल सकता है।


आप इस बात से कैसे बचते हैं कि कलर साइकलर के अगले तत्व को बदलने से साइकलर की स्थिति बदल जाती है?
kazemakase

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 का उपयोग करता है

संपादित करें: टिप्पणी के लिए धन्यवाद, ऐसा लगता है कि इट्रेटर की नकल करना संभव नहीं है। एक विचार यह होगा कि एक पूरा चक्र डंप किया जाए और आप किस मूल्य का उपयोग कर रहे हैं, उस पर नज़र रखें।

Edit2: ठीक है, यह आपको अगला रंग देगा और एक नया पुनरावृत्ति करेगा जो ऐसा व्यवहार करता है जैसे कि अगले को नहीं बुलाया गया था। यह रंग के आदेश को संरक्षित नहीं करता है, बस अगले रंग मूल्य, मैं आपको छोड़ देता हूं।

यह निम्न आउटपुट देता है, सूचना है कि प्लॉट में स्थिरता सूचकांक से मेल खाती है, उदाहरण के लिए पहला जी सबसे निचला ग्राफ है और इसी तरह।

#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

रंग घुमाएँ


धन्यवाद! बस स्पष्ट करने के लिए, ऐसा नहीं लगता है कि एक प्रति लौटाता है, बल्कि वास्तविक चक्र का संदर्भ देता है। इसलिए, इंद्रधनुष को बुलाना। स्नेक्स () वास्तव में बदलने जा रहा है कि अगला प्लॉट कैसा दिखेगा।
mwaskom

5

मैं सिर्फ @Andi के ऊपर जो कहना चाहता हूं, उस पर जोड़ना चाहता हूं। चूँकि color_cycleMatplotlib 1.5 में पदावनत किया गया है, आपको इसका उपयोग करना होगा prop_cycler, हालाँकि, Andi के समाधान ( ax._get_lines.prop_cycler.next()['color']) ने आपके लिए इसे वापस लौटा दिया है:

गुण: 'itertools.cycle' ऑब्जेक्ट में कोई विशेषता नहीं है 'अगला'

मेरे लिए काम करने वाला कोड था: next(ax._get_lines.prop_cycler)जो वास्तव में @ जो-किंगटन की मूल प्रतिक्रिया से दूर नहीं है।

व्यक्तिगत रूप से, मैं ट्विनक्स () अक्ष बनाते समय इस समस्या में भाग गया, जो कि रंग साइकिलर को रीसेट करता है। मुझे रंगों के चक्र को सही ढंग से बनाने के लिए एक तरीके की आवश्यकता थी क्योंकि मैं उपयोग कर रहा था style.use('ggplot')। ऐसा करने का एक आसान / बेहतर तरीका हो सकता है, इसलिए मुझे ठीक करने के लिए स्वतंत्र महसूस करें।


कृपया अपनी पोस्ट को एक उत्तर के रूप में प्रारूपित करें , चर्चा सामग्री के रूप में नहीं (अन्यथा यह एक टिप्पणी है), आपका मुख्य बिंदु next(ax._get_lines.prop_cycler)यह संभव विकल्प है।
उमनोबेह

@ करसन आप कैसे इससे बचते हैं कि कॉल next(ax._get_lines.prop_cycler)वास्तव में कलर साइकलर की स्थिति को बदल देता है?
kazemakase

यह वास्तव में मैं क्या करने का प्रयास कर रहा था - की स्थिति को बदलो prop_cycler। यदि आप इस प्रश्न का स्वीकृत उत्तर पढ़ते हैं, तो आप देखेंगे कि prop_cyclerइसके राज्य को बदले बिना राज्य तक पहुँचने का कोई तरीका नहीं है क्योंकि यह एक चलने योग्य है।
कार्सन

आपके द्वारा इंगित की गई त्रुटि एक पायथन 2 / पायथन 3 अंतर है। इसे इंगित करने के लिए धन्यवाद, मैंने तदनुसार अपना उत्तर संपादित किया।
एंडी

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

चक्र की स्थिति को बदलने के बिना वर्तमान रंग प्राप्त करने के लिए ।


टी एल; डॉ

रंग (और पूर्ण शैली) चक्र कहाँ संग्रहीत किया जाता है?

शैली चक्र को दो अलग-अलग स्थानों में संग्रहीत किया जाता है, एक डिफ़ॉल्ट के लिए , और एक वर्तमान अक्षों के लिए (संभालने 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'>

डिफ़ॉल्ट चक्र में चक्र करने के लिए कई कुंजी (गुण) हो सकते हैं, और कोई केवल रंग प्राप्त कर सकता है:

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.