Сброс цветового цикла в Matplotlib
Скажем, у меня есть данные о 3 торговых стратегиях, каждая из которых имеет транзакционные издержки и без них. Я хочу построить на тех же осях временные ряды каждого из 6 вариантов (3 стратегии * 2 торговые издержки). Я хотел бы, чтобы линии "с транзакционной стоимостью" были нанесены с alpha=1
а также linewidth=1
в то время как я хочу, чтобы "без трансакционных издержек" был нанесен на график с alpha=0.25
а также linewidth=5
, Но я бы хотел, чтобы цвет был одинаковым для обеих версий каждой стратегии.
Я хотел бы что-то вроде:
fig, ax = plt.subplots(1, 1, figsize=(10, 10))
for c in with_transaction_frame.columns:
ax.plot(with_transaction_frame[c], label=c, alpha=1, linewidth=1)
****SOME MAGIC GOES HERE TO RESET THE COLOR CYCLE
for c in no_transaction_frame.columns:
ax.plot(no_transaction_frame[c], label=c, alpha=0.25, linewidth=5)
ax.legend()
Какой код следует поместить в указанную строку для сброса цветового цикла, чтобы он возвращался к началу при запуске второго цикла?
5 ответов
Вы можете сбросить цветовой цикл до исходного с помощью Axes.set_color_cycle. Глядя на код для этого, есть функция для выполнения реальной работы:
def set_color_cycle(self, clist=None):
if clist is None:
clist = rcParams['axes.color_cycle']
self.color_cycle = itertools.cycle(clist
И метод на осях, который использует его:
def set_color_cycle(self, clist):
"""
Set the color cycle for any future plot commands on this Axes.
*clist* is a list of mpl color specifiers.
"""
self._get_lines.set_color_cycle(clist)
self._get_patches_for_fill.set_color_cycle(clist)
Это в основном означает, что вы можете вызвать set_color_cycle с None в качестве единственного аргумента, и он будет заменен циклом по умолчанию, найденным в rcParams['axes.color_cycle'].
Я попробовал это с помощью следующего кода и получил ожидаемый результат:
import matplotlib.pyplot as plt
import numpy as np
for i in range(3):
plt.plot(np.arange(10) + i)
# for Matplotlib version < 1.5
plt.gca().set_color_cycle(None)
# for Matplotlib version >= 1.5
plt.gca().set_prop_cycle(None)
for i in range(3):
plt.plot(np.arange(10, 1, -1) + i)
plt.show()
В качестве ответа, данного @pelson, используется set_color_cycle
и это устарело в Matplotlib 1.5, я подумал, что было бы полезно иметь обновленную версию его решения, используя set_prop_cycle
:
import matplotlib.pyplot as plt
import numpy as np
for i in range(3):
plt.plot(np.arange(10) + i)
plt.gca().set_prop_cycle(None)
for i in range(3):
plt.plot(np.arange(10, 0, -1) + i)
plt.show()
Отметим также, что мне пришлось изменить np.arange(10,1,-1)
в np.arange(10,0,-1)
, Первый дал массив только из 9 элементов. Вероятно, это связано с использованием разных версий Numpy. Мой 1.10.2.
РЕДАКТИРОВАТЬ: устранена необходимость использования rcParams
, Спасибо @divenex за то, что указал на это в комментарии.
Поскольку вы упомянули, что используете seaborn, я бы порекомендовал сделать следующее:
with sns.color_palette(n_colors=3):
ax.plot(...)
ax.plot(...)
Это установит цветовую палитру для использования текущего активного цветового цикла, но только первые три цвета из него. Это также универсальное решение для любого времени, когда вы хотите установить временный цветовой цикл.
Обратите внимание, что единственное, что на самом деле должно быть под with
Блок это все, что вы делаете, чтобы создать Axes
объект (т.е. plt.subplots
, fig.add_subplot()
, так далее.). Это просто из-за того, как работает сам цветовой цикл matplotlib.
Делать то, что вы конкретно хотите, "сбрасывать" цветовой цикл, возможно, но это хак, и я бы не стал делать это в любом виде производственного кода. Вот как это могло произойти:
f, ax = plt.subplots()
ax.plot(np.random.randn(10, 3))
ax._get_lines.color_cycle = itertools.cycle(sns.color_palette())
ax.plot(np.random.randn(10, 3), lw=5, alpha=.25)
Просто выберите ваши цвета и назначьте их списку, а затем, когда вы строите свои данные, выполняйте итерации по zip
объект, содержащий ваш столбец и цвет, который вы хотите.
colors = ['red', 'blue', 'green']
for col, color in zip(colors, with_transaction_frame.columns):
ax.plot(with_transaction_frame[col], label=col, alpha=1.0, linewidth=1.0, color=color)
for col, color in zip(no_transaction_frame.columns):
ax.plot(no_transaction_frame[col], label=col, alpha=0.25, linewidth=5, color=color)
zip
создает список, который объединяет элементы из каждого из ваших списков. Это позволяет вам легко перебирать и то и другое одновременно.
Вы можете получить цвета от морского бора как это: colors = sns.color_palette()
, Ответ Ffisegydd тогда будет отлично работать. Вы также можете получить цвет для построения графика, используя оператор модуля / остатка (%): mycolor = colors[icolumn % len(colors]
, Я часто использую этот подход сам. Так что вы могли бы сделать:
for icol, column in enumerate(with_transaction_frame.columns):
mycolor = colors[icol % len(colors]
ax.plot(with_transaction_frame[col], label=col, alpha=1.0, color=mycolor)
Однако ответ Ффизегида может быть более "питоническим".
В дополнение к уже отличным ответам вы можете рассмотреть возможность использования цветовой карты:
import matplotlib.pyplot as plt
import numpy as np
cmap = plt.cm.viridis
datarange = np.arange(4)
for d in datarange:
# generate colour by feeding float between 0 and 1 to colormap
color = cmap(d/np.max(datarange))
plt.plot(np.arange(5)+d, c=color)
for d in datarange:
# generate colour by feeding float between 0 and 1 to colormap
color = cmap(d/np.max(datarange))
plt.plot(-np.arange(5)+d, c=color)
https://stackru.com/images/8c605fe73fbf97d365ee41707f5732ba3ea37627.png