Как задать пользовательские цвета для гистограммы pandas / matplotlib

86

Я только начал использовать pandas / matplotlib в качестве замены Excel для создания столбчатых диаграмм с накоплением. Я столкнулся с проблемой

(1) в палитре по умолчанию всего 5 цветов, поэтому, если у меня больше 5 категорий, цвета повторяются. Как я могу указать больше цветов? В идеале, градиент с начальным и конечным цветами и способ динамически генерировать n цветов между ними?

(2) цвета не очень приятны на вид. Как указать собственный набор из n цветов? Или градиент тоже подойдет.

Ниже приведен пример, иллюстрирующий оба вышеперечисленных пункта:

  4 from matplotlib import pyplot
  5 from pandas import *
  6 import random
  7 
  8 x = [{i:random.randint(1,5)} for i in range(10)]
  9 df = DataFrame(x)
 10 
 11 df.plot(kind='bar', stacked=True)

И результат такой:

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

vasek1
источник
Есть довольно простой способ получить частичную цветовую карту. См. Это решение ниже
Тед Петру

Ответы:

120

Вы можете указать colorпараметр в виде списка непосредственно в plotфункции.

from matplotlib import pyplot as plt
from itertools import cycle, islice
import pandas, numpy as np  # I find np.random.randint to be better

# Make the data
x = [{i:np.random.randint(1,5)} for i in range(10)]
df = pandas.DataFrame(x)

# Make a list by cycling through the colors you care about
# to match the length of your data.
my_colors = list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(df)))

# Specify this list of colors as the `color` option to `plot`.
df.plot(kind='bar', stacked=True, color=my_colors)

Чтобы определить свой собственный список, вы можете выполнить несколько из следующих действий или просто найти методы Matplotlib для определения элемента цвета по его значениям RGB и т. Д. Вы можете усложнить, как хотите.

my_colors = ['g', 'b']*5 # <-- this concatenates the list to itself 5 times.
my_colors = [(0.5,0.4,0.5), (0.75, 0.75, 0.25)]*5 # <-- make two custom RGBs and repeat/alternate them over all the bar elements.
my_colors = [(x/10.0, x/20.0, 0.75) for x in range(len(df))] # <-- Quick gradient example along the Red/Green dimensions.

Последний пример дает мне следующий простой градиент цветов:

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

Я не играл с ним достаточно долго, чтобы понять, как заставить легенду выбирать определенные цвета, но я уверен, что вы справитесь.

В целом, тем не менее, большой совет - просто использовать функции из Matplotlib напрямую. Вызов их из Pandas - это нормально, но я считаю, что вы получаете лучшие варианты и производительность, вызывая их прямо из Matplotlib.

Эли
источник
3
Незначительная ошибка: my_colors = [cycle (['b', 'r', 'g', 'y', 'k']). Next () для i в диапазоне (len (df))] даст 'b' каждый раз в python 2.7. Вместо этого вы должны использовать list (islice (cycle (['b', 'r', 'g', 'y', 'k']), None, len (df))).
vkontori
Спасибо, наверное, я бы этого не заметил. Другой вариант - сначала создать цикл, а затем просто вызвать его nextфункцию внутри понимания.
ely
Ага. это = цикл (['b', 'r', 'g', 'y', 'k']); my_colors = [next (it) for i in xrange (len (df))] тоже
подрежет
1
С установленными сегодня pandas и matplotlib приведенный выше код ничего не генерирует для меня, хотя он работает.
kakyo
@kakyo Вы работаете в обычном интерпретаторе, IPython или из оболочки (или что-то еще)? В зависимости от того, в какой среде вы выполняете этот код, вам может потребоваться включить интерактивный режим для matplotlib или установить pylab.ion()для интерактивного pylab.
Эли 07
54

Я обнаружил, что самый простой способ - использовать colormapпараметр .plot()с одним из предустановленных цветовых градиентов:

df.plot(kind='bar', stacked=True, colormap='Paired')

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

Вы можете найти здесь большой список предустановленных цветовых карт .

цветовые карты

Александр
источник
19
в моем случае это дает только один цвет на всех столбцах
tsando
Я нашел эти цветовые карты списки полезны matplotlib.org/examples/color/colormaps_reference.html gallantlab.github.io/colormaps.html
Al Po
15

Чтобы получить более подробный ответ о создании собственных цветовых карт, я настоятельно рекомендую посетить эту страницу.

Если этот ответ слишком трудоемок, вы можете быстро создать свой собственный список цветов и передать их в colorпараметр. Все cmцветовые карты находятся в модуле matplotlib. Давайте получим список из 30 значений цвета RGB (плюс альфа) из перевернутой палитры инферно. Для этого сначала получите цветовую карту, а затем передайте ей последовательность значений от 0 до 1. Здесь мы используем np.linspaceдля создания 30 одинаковых значений между .4 и .8, которые представляют эту часть цветовой карты.

from matplotlib import cm
color = cm.inferno_r(np.linspace(.4, .8, 30))
color

array([[ 0.865006,  0.316822,  0.226055,  1.      ],
       [ 0.851384,  0.30226 ,  0.239636,  1.      ],
       [ 0.832299,  0.283913,  0.257383,  1.      ],
       [ 0.817341,  0.270954,  0.27039 ,  1.      ],
       [ 0.796607,  0.254728,  0.287264,  1.      ],
       [ 0.775059,  0.239667,  0.303526,  1.      ],
       [ 0.758422,  0.229097,  0.315266,  1.      ],
       [ 0.735683,  0.215906,  0.330245,  1.      ],
       .....

Затем мы можем использовать это для построения графика, используя данные из исходного сообщения:

import random
x = [{i: random.randint(1, 5)} for i in range(30)]
df = pd.DataFrame(x)
df.plot(kind='bar', stacked=True, color=color, legend=False, figsize=(12, 4))

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

Тед Петру
источник
2
Вот документация к другим цветным картам, кроме inferno_r: matplotlib.org/examples/color/colormaps_reference.html
tsando
1
Я следил за этим фрагментом, но мой цветовой массив всегда имеет одинаковые значения.
FaCoffee