是否可以查询matplotlib颜色周期的当前状态?换句话说,有没有一种功能get_cycle_state
可以按照以下方式运行?
>>> plot(x1, y1)
>>> plot(x2, y2)
>>> state = get_cycle_state()
>>> print state
2
我希望状态是绘图中将使用的下一个颜色的索引。或者,如果它返回下一个颜色(在上面的示例中,默认循环为“ r”),那也可以。
Answers:
没有用于访问底层迭代器的“面向用户”(也称为“公共”)方法,但是您可以通过“专用”(按惯例)方法来访问它。但是,如果iterator
不更改它,您将无法获得它的状态。
快速说明:您可以通过多种方式(例如ax.set_color_cycle
,版本<1.5或版本ax.set_prop_cycler
> = 1.5)设置颜色/属性周期。在此处查看1.5或更高版本的示例,或此处的先前样式。
但是,虽然没有公开的方法可访问Iterable,但是您可以ax
通过_get_lines
helper类实例为给定的axis对象()访问它。 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
并产生adict
的属性,而不仅仅是颜色。
总而言之,您将执行以下操作:
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
答案中建议的等效项。我不确定您是否能获得仅这些颜色的迭代,我需要探索更多。
注意:在最新版本的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
,但是Andi的解决方案(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
颜色(和完整样式)循环存储在哪里?
样式周期被存储在两个不同的地方,一个用于缺省,和一个用于电流轴(假设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
。