Подтвердить что ты не робот

Создание более 20 уникальных цветов легенды с использованием matplotlib

Я рисую 20 разных строк на одном участке, используя matplotlib. Я использую цикл for для построения и маркировки каждой строки своим ключом, а затем использую функцию легенды

for key in dict.keys():
    plot(x,dict[key], label = key)
graph.legend()

Но используя этот способ, график повторяет много цветов в легенде. Есть ли способ гарантировать, что для каждой строки назначается уникальный цвет с использованием matplotlib и более 20 строк?

спасибо

4b9b3361

Ответ 1

Ответ на ваш вопрос связан с двумя другими вопросами SO.

Ответ на Как выбрать новый цвет для каждой построенной строки в фигуре в matplotlib? объясняет, как определить список цветов по умолчанию, выберите следующий цвет для сюжета. Это делается с помощью метода Axes.set_color_cycle .

Вы хотите получить правильный список цветов, хотя это проще всего сделать, используя цветовую карту, как объясняется в ответе на этот вопрос: Создайте генератор цветов из заданная цветовая карта в matplotlib. Там цветовая карта принимает значение от 0 до 1 и возвращает цвет.

Итак, для ваших 20 строк вы хотите циклически переключаться с 0 на 1 с шагом 1/20. В частности, вы хотите циклировать форму от 0 до 19/20, потому что 1 отображает обратно на 0.

Это выполняется в этом примере:

import matplotlib.pyplot as plt
import numpy as np

NUM_COLORS = 20

cm = plt.get_cmap('gist_rainbow')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_color_cycle([cm(1.*i/NUM_COLORS) for i in range(NUM_COLORS)])
for i in range(NUM_COLORS):
    ax.plot(np.arange(10)*(i+1))

fig.savefig('moreColors.png')
plt.show()

Это результат:

Yosemitebear Mountain Giant Double Rainbow 1-8-10

Альтернативное, лучшее (дискуссионное) решение:

Существует альтернативный способ использования объекта ScalarMappable для преобразования диапазона значений в цвета. Преимущество этого метода заключается в том, что вы можете использовать нелинейный Normalization для преобразования из индекса строки в фактический цвет. Следующий код дает тот же точный результат:

import matplotlib.pyplot as plt
import matplotlib.cm as mplcm
import matplotlib.colors as colors
import numpy as np

NUM_COLORS = 20

cm = plt.get_cmap('gist_rainbow')
cNorm  = colors.Normalize(vmin=0, vmax=NUM_COLORS-1)
scalarMap = mplcm.ScalarMappable(norm=cNorm, cmap=cm)
fig = plt.figure()
ax = fig.add_subplot(111)
# old way:
#ax.set_color_cycle([cm(1.*i/NUM_COLORS) for i in range(NUM_COLORS)])
# new way:
ax.set_color_cycle([scalarMap.to_rgba(i) for i in range(NUM_COLORS)])
for i in range(NUM_COLORS):
    ax.plot(np.arange(10)*(i+1))

fig.savefig('moreColors.png')
plt.show()

Ответ 2

У меня был сюжет с 12 строками, и мне было трудно отличить строки с подобными цветами, когда я пробовал метод Янна. Мои строки также отображались в парах, поэтому я использовал один и тот же цвет для двух строк в каждой паре и использовал две разные ширины линий. Вы также можете изменить стиль линии, чтобы получить больше комбинаций.

Вы можете использовать set_prop_cycle(), но я просто изменил объекты линии после вызова plot().

Вот пример Yann с тремя разными ширинами линий:

import matplotlib.pyplot as plt
import numpy as np

NUM_COLORS = 20

cm = plt.get_cmap('gist_rainbow')
fig = plt.figure()
ax = fig.add_subplot(111)
for i in range(NUM_COLORS):
    lines = ax.plot(np.arange(10)*(i+1))
    lines[0].set_color(cm(i//3*3.0/NUM_COLORS))
    lines[0].set_linewidth(i%3 + 1)

fig.savefig('moreColors.png')
plt.show()

Пример графика с шириной линии

Здесь тот же пример с разными стилями линий. Конечно, вы могли бы объединить эти два, если хотите.

import matplotlib.pyplot as plt
import numpy as np

NUM_COLORS = 20
LINE_STYLES = ['solid', 'dashed', 'dashdot', 'dotted']
NUM_STYLES = len(LINE_STYLES)

cm = plt.get_cmap('gist_rainbow')
fig = plt.figure()
ax = fig.add_subplot(111)
for i in range(NUM_COLORS):
    lines = ax.plot(np.arange(10)*(i+1))
    lines[0].set_color(cm(i//NUM_STYLES*float(NUM_STYLES)/NUM_COLORS))
    lines[0].set_linestyle(LINE_STYLES[i%NUM_STYLES])

fig.savefig('moreColors.png')
plt.show()

Пример сюжета с стилями линии