Як отримати різні кольорові лінії для різних сюжетів в одній фігурі?


202

Я використовую matplotlibдля створення сюжетів. Я повинен ідентифікувати кожен сюжет з іншим кольором, який повинен автоматично генеруватися Python.

Чи можете ви, будь ласка, дати мені спосіб розмістити різні кольори для різних ділянок в одній фігурі?

Відповіді:


424

Matplotlib робить це за замовчуванням.

Наприклад:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.show()

Основний сюжет, що демонструє кольорову велосипедність

І, як ви, можливо, вже знаєте, ви можете легко додати легенду:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Основний сюжет з легендою

Якщо ви хочете керувати кольорами, які будуть переходити через:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow'])

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Сюжет, що показує контроль за кольоровим циклом за замовчуванням

Якщо ви не знайомі з matplotlib, підручник - це гарне місце для початку .

Редагувати:

По-перше, якщо у вас є багато (> 5) речей, які ви хочете побудувати на одній фігурі:

  1. Розмістіть їх на різних ділянках (розгляньте можливість використання декількох підзаготівок на одній фігурі), або
  2. Використовуйте щось інше, ніж колір (наприклад, стилі маркера або товщину ліній), щоб розрізняти їх.

Інакше ти збираєшся накрутити дуже безладний сюжет! Будьте приємні, хто коли-небудь збирається читати все, що ви робите, і не намагайтеся набити 15 різних речей на одній фігурі !!

Крім того, багато людей мають різну ступінь кольорових слідів, і розрізнити численні тонко різні кольори важче для більшості людей, ніж ви можете зрозуміти.

Зважаючи на це, якщо ви дійсно хочете розмістити 20 ліній на одній осі з 20 відносно різними кольорами, ось один із способів:

import matplotlib.pyplot as plt
import numpy as np

num_plots = 20

# Have a look at the colormaps here and decide which one you'd like:
# http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html
colormap = plt.cm.gist_ncar
plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))

# Plot several different functions...
x = np.arange(10)
labels = []
for i in range(1, num_plots + 1):
    plt.plot(x, i * x + 5 * i)
    labels.append(r'$y = %ix + %i$' % (i, 5*i))

# I'm basically just demonstrating several different legend options here...
plt.legend(labels, ncol=4, loc='upper center', 
           bbox_to_anchor=[0.5, 1.1], 
           columnspacing=1.0, labelspacing=0.0,
           handletextpad=0.0, handlelength=1.5,
           fancybox=True, shadow=True)

plt.show()

Унікальні кольори для 20 ліній на основі заданої кольорової карти


17
Зверніть увагу на останній приклад, що в нових версіях matplotlib цей файл set_color_cycleзастарілий, тому ця лінія повинна бути plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))і просто змінити відповідно plt.cm.YOUR_PREFERED_COLOR_MAPдо ваших потреб.
Нейт

1
@JoeKington: Пояснення було чудове, дуже дякую
Rika

це чудово. чи є спосіб зробити їх інтерактивними? наприклад, в RI конвертувати ggplot в ggplotly (), і сюжет стає html інтерактивним
kRazzy R

Я переконаний, що ОП знала, що кольори Matplotlib мають відповідні різні криві в одному сюжеті (в одному axes) і запитала про зміну кольору однієї лінії на різних ділянках (різних axes) ... Це сказало, відмінною відповіддю на важливу питання (можливо, відрізняється від того, що задав ОП, але ніхто не може сказати, тому що вони задали це одне єдине питання і зникли!) - +1
gboffi

37

Встановлення їх пізніше

Якщо ви не знаєте кількість сюжетів, на яких збираєтеся побудувати сюжет, ви можете змінити кольори, як тільки ви побудували їх, отримуючи номер безпосередньо з ділянки .lines, використовуючи це рішення:

Деякі випадкові дані

import matplotlib.pyplot as plt
import numpy as np

fig1 = plt.figure()
ax1 = fig1.add_subplot(111)


for i in range(1,15):
    ax1.plot(np.array([1,5])*i,label=i)

Код, який вам потрібен:

colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired   
colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))]
for i,j in enumerate(ax1.lines):
    j.set_color(colors[i])
  

ax1.legend(loc=2)

Результат такий:введіть тут опис зображення


8

TL; DR Ні, це неможливо зробити автоматично . Так, можливо.

import matplotlib.pyplot as plt
my_colors = plt.rcParams['axes.prop_cycle']() # <<< note that we CALL the prop_cycle
fig, axes = plt.subplots(2,3)
for ax in axes.flatten(): ax.plot((0,1), (0,1), **next(my_colors))

введіть тут опис зображення Кожен сюжет ( axes) у фігурі ( figure) має свій цикл кольорів - якщо ви не застосовуєте різний колір для кожного сюжету, всі ділянки мають однаковий порядок кольорів, але, якщо ми трохи розтягнемо, що означає "автоматично" , це можна зробити.


ОП написала

[...] Я повинен ідентифікувати кожен сюжет з іншим кольором, який повинен бути автоматично сформований [Matplotlib].

Але ... Matplotlib автоматично генерує різні кольори для кожної різної кривої

In [10]: import numpy as np
    ...: import matplotlib.pyplot as plt

In [11]: plt.plot((0,1), (0,1), (1,2), (1,0));
Out[11]:

введіть тут опис зображення

То чому запит на ОП? Якщо ми продовжимо читати, маємо

Чи можете ви, будь ласка, дати мені спосіб розмістити різні кольори для різних ділянок в одній фігурі?

і це має сенс, тому що кожен сюжет (кожен axesза мовою Матплотліба) має свій власний color_cycle(а точніше, у 2018 році свій prop_cycle), і кожен сюжет ( axes) повторно використовує ті самі кольори в одному порядку.

In [12]: fig, axes = plt.subplots(2,3)

In [13]: for ax in axes.flatten():
    ...:     ax.plot((0,1), (0,1))

введіть тут опис зображення

Якщо це сенс оригінального питання, одна можливість полягає в тому, щоб явно назвати інший колір для кожного сюжету.

Якщо графіки (як це часто буває) генеруються в циклі, у нас повинна бути додаткова змінна петля, щоб замінити колір, автоматично вибраний Matplotlib.

In [14]: fig, axes = plt.subplots(2,3)

In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'):
    ...:     ax.plot((0,1), (0,1), short_color_name)

введіть тут опис зображення

Інша можливість - інстанціювати циклічний об'єкт

from cycler import cycler
my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.])
actual_cycler = my_cycler()

fig, axes = plt.subplots(2,3)
for ax in axes.flat:
    ax.plot((0,1), (0,1), **next(actual_cycler))

введіть тут опис зображення

Зауважте, що type(my_cycler)є, cycler.Cyclerале type(actual_cycler)є itertools.cycle.


3

Я хотів би запропонувати незначне вдосконалення щодо останньої відповіді циклу, наведеної в попередньому дописі (ця публікація є правильною і все одно повинна бути прийнята). Неявне припущення, зроблене при маркуванні останнього прикладу, полягає в тому, що plt.label(LIST)ставиться номер мітки X LISTз рядком, відповідним X-му часу plot. Я раніше стикався з проблемами такого підходу. Рекомендований спосіб створення легенд та налаштування їх етикетки відповідно до документації на matplotlibs ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item ) - це тепле відчуття, що етикетки йдуть разом із точними сюжетами, на які ви думаєте, що вони роблять:

...
# Plot several different functions...
labels = []
plotHandles = []
for i in range(1, num_plots + 1):
    x, = plt.plot(some x vector, some y vector) #need the ',' per ** below
    plotHandles.append(x)
    labels.append(some label)
plt.legend(plotHandles, labels, 'upper left',ncol=1)

**: Легенди Matplotlib не працюють


3
Тільки fyi: ви також можете використовувати kwarg "label", щоб побудувати, а потім викликати легенду без жодних аргументів.
Джо Кінгтон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.