matplotlib 색상주기 상태 가져 오기


90

matplotlib 색상주기의 현재 상태를 쿼리 할 수 ​​있습니까? 즉 get_cycle_state, 다음과 같은 방식으로 작동 하는 기능 이 있습니까?

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

상태가 플롯에 사용될 다음 색상의 인덱스가 될 것으로 예상하는 곳. 또는 다음 색상 (위의 예에서 기본주기에 대한 "r")을 반환하는 경우에도 괜찮습니다.


이, 심지어 현재 상태를 변경하지 않고, 수행 볼 수 있습니다 아래의 대답을
ReinstateMonicaCellio sancho.s

답변:


109

색상 순환 반복기에 액세스

기본 반복기에 액세스하는 "사용자 지향"(일명 "공용") 방법은 없지만 "개인"(관례에 따라) 방법을 통해 액세스 할 수 있습니다. 그러나 iterator변경하지 않고 는의 상태를 얻을 수 없습니다 .

색상주기 설정

참고 : 다양한 방법으로 색상 / 속성주기를 설정할 수 있습니다 (예 : ax.set_color_cycle버전 <1.5 또는 ax.set_prop_cycler> = 1.5). 여기에서 버전 1.5 이상에 대한 예제를 보거나 여기 에서 이전 스타일을 살펴보십시오 .

기본 반복기에 액세스

그러나 iterable에 액세스 할 수있는 공용 메서드는 없지만 도우미 클래스 인스턴스를 ax통해 주어진 axes 객체 ( )에 대해 액세스 할 수 있습니다 _get_lines. 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에서 이것은 library사용하도록cycler 변경 되었으며, iterable이 prop_cycler대신 호출 되어 색상 대신 color_cyclea dictof 속성을 생성합니다 .

대체로 다음과 같이 할 수 있습니다.

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

12
특정 물체의 색상 만 일치시키고 싶다면 항상 색상을 잡을 수 있습니다. 예를 들어 이전에 플로팅 된 선의 색상을 가져 오는 데 line, = ax.plot(x, y)사용 line.get_color()합니다.
Joe Kington

3
ax._get_lines.color_cycle1.5에 더 이상 존재하지 않는 것 같습니다 .
endolith

6
나는 (거의) 동등한 것은 ax._get_lines.prop_cycler당신 이 대답에서 제안 된 것과 동등한 것을 수행하기 위해 if 'color' in ax._get_lines._prop_keys:다음 과 같은 구성을 가질 수 있는 반복 가능한 것이라고 생각합니다. 색상 만 반복 할 수 있는지 여부는 확실하지 않습니다. 더 자세히 살펴 봐야합니다. next(ax._get_lines.prop_cycler)['color']color_cycle
J Richard Snape

1
@endolith 물론입니다 (그리고 감사합니다)-그러나 나는 Joe의 이미 매우 좋고 받아 들여진 대답에 앉아있는 것이 더 나을 것이라고 느꼈습니다. 그는 월요일까지에 넣어로 라운드하지 않는 경우 - 나는 대신 무서워 "대답 - 인 - 주석"의이 적절한 대답을 맡기 겠소
J 리처드 스네이프

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']Python 2 또는 3 (또는 Python 2 ) ax._get_lines.prop_cycler.next()['color']에서 사용해야 합니다.

가능하면 @ joe-kington의 답변 하단에 표시된보다 직접적인 접근 방식을 사용하십시오. 대로 _get_lines되지는 미래에 있지 역 호환 방식으로 다시 변경 될 수 있습니다 API-에 직면.


색상 순환기의 다음 요소를 쿼리하면 순환기의 상태가 변경되는 것을 어떻게 방지 할 수 있습니까?
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을 사용하는 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

5

@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)가능한 대안이라는 것입니다.
UmNyobe

@Carson 호출이 next(ax._get_lines.prop_cycler)실제로 색상 순환기의 상태를 변경 하지 않도록하려면 어떻게해야 합니까?
kazemakase

이것이 실제로 제가하려는 작업 prop_cycler입니다.. 이 질문에 대한 대답을 읽으면 prop_cycler반복 가능하기 때문에 상태를 변경하지 않고 상태에 액세스 할 수있는 방법이 없음을 알 수 있습니다 .
Carson

지적한 오류는 Python 2 / Python 3의 차이점입니다. 이것을 지적 해 주셔서 감사합니다. 그에 따라 답변을 수정했습니다.
Andi

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

색상 (및 완전한 스타일)주기는 어디에 저장됩니까?

스타일주기는 두 개의 서로 다른 장소의 하나에 저장되어 기본 및 하나 현재 (가정 축 import matplotlib.pyplot as pltax축 처리기입니다) :

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.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.