Сопоставить определенное значение строки с определенным цветом в matplotlib.pyplot.imshow () - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть pandas.dataframe, который выглядит следующим образом:

columns    0    1   2   3   4   5
           A    A   A   A   B   B
           B    B   B   C   C   D
           D    D   E   E   F   F

Я хочу построить это с помощью pyplot.imshow(), указав следующую цветовую карту:

color_dict = {
    "A": "#DA291E",
    "B": "#83DF39",
    "C": "#E8132d",
    "D": "#008933",
    "E": "#006CB3",
    "F": "#52BFEC"
}

Если бы я былпостроение bar или scatter Я мог бы просто позвонить с аргументом color=a_list_of_colors, но это не работает с imshow().

Вместо этого мне нужно позвонить с cmap, но, насколько я понимаю, невозможно создать карту, в которой определенный цвет сопоставляется со значением.

Это означает, что мне нужно создать такую ​​цветовую карту:

    from matplotlib.colors import ListedColormap 

    _colors = ["#DA291E", "DA291E", "DA291E", "DA291E" 
               "#83DF39", "#83DF39", "#83DF39", "#83DF39", "#83DF39", #...and so on]
    cmap = ListedColormap(_colors, name="custom_cmap")

Но есть ли лучший способ сделать это?


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

Я начинаю с создания color_list на основе длинной series версии моего df выше изатем преобразуйте этот список в цветовую карту:

color_list = list(series.map(color_dict))
custom_cmap = ListedColormap(color_list, name="custom_cmap")

Длинный series в основном выглядит следующим образом:

A
A
A
A
B
B
B
B
B
C
#...and so on

Пятый элемент в моем df равен B, и когдаЯ печатаю custom_cmap.__dict__.colors[4], я получаю #83DF39, что соответствует строковому значению B в моем df.Таким образом, отображение правильное.

Проблема возникает, когда я звоню plt.imshow() с cmap=custom_cmap, так как он не следует cmap - некоторые значения получают неправильный цвет.

MyПервой мыслью было, что я испортил порядок, то есть color_list не следовал порядку df, но это так.

Выше df содержит 18 значений, а color_list тоже,Последнее значение в df - это F, что означает, что последний цвет в color_list должен быть #52BFEC, что и есть.


Добавление дополнительного кода.

# Begin by converting strings to any number since plt.imshow() needs numbers
float_dict = {
    'A': 0.0,
    'B': 1.0,
    'C': 2.0,
    'D': 3.0,
    'E': 4.0,
    'F': 5.0,
    'G': 6.0,
    'H': 7.0,
    'I': 8.0
}

converted_series = series.map(float_dict).copy()

# Map each float to a specific color
color_dict = {
    0.0: '#DA291E',
    1.0: '#E7112d',
    2.0: '#83CD39',
    3.0: '#009934',
    4.0: '#007AB3',
    5.0: '#54BDEC',
    6.0: '#000066',
    7.0: '#DDDD11',
    8.0: '#572B84',
}

# Create a cmap from a color list
color_list = list(converted_series.map(color_dict))
custom_cmap = ListedColormap(color_list, name="custom_cmap")

# Widen the series into a df
df = series_to_wide_df(converted_series, n_columns=8)

# Plot it
plt.imshow(df, cmap=custom_cmap, interpolation='none')

Результат выше показан на изображении ниже.

enter image description here

  • Обратите внимание, что данные на этом изображении не являютсяте же данные в df в оригинальном сообщении.

Я тестировал другое color_dict:

color_dict = {
    0.0: '#FF0000',
    1.0: '#FF0000',
    2.0: '#FF0000',
    3.0: '#FF0000',
    4.0: '#FF0000',
    5.0: '#000000',
    6.0: '#000000',
    7.0: '#000000',
    8.0: '#000000'
}

Но цвета по-прежнему не отображаютсяправильно.С этими цветами 1.0, 2.0, 6.0, 7.0 и некоторые 8.0 получают красный цвет.

1 Ответ

0 голосов
/ 14 сентября 2018

Довольно сложно понять, где предложенный код работает неправильно, без возможности его запуска.

Следующее создаст словарь, отображающий буквы в числа и применяет его к кадру данных.Затем он создаст цветовую карту с таким количеством цветов, сколько есть (возможных) значений в кадре данных.Тогда построение графиков с помощью imshow работает нормально, когда цветовая карта нормализуется между нулем и количеством элементов в цветовой карте.(Эта нормализация может быть просто полезна, если не все возможные значения фактически встречаются в конкретном кадре данных, например, в случае, когда буквы A и H отсутствуют.)

import numpy as np; np.random.seed(42)
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap


df = pd.DataFrame(np.random.choice(list("ABCDEFGH"), size=(8,8)))
print(df)

#mapping from letters to numbers
letter2num = dict(zip(list("ABCDEFGH"), np.arange(8)))
df2 = pd.DataFrame(np.array( [letter2num[i] for i in df.values.flat] ).reshape(df.shape))


#produce colormap with as many colors as there are unique values in df
colors = ["pink", "red", "violet", "blue", 
          "turquoise", "limegreen", "gold", "brown"]  # use hex colors here, if desired.
cmap = ListedColormap(colors)

fig, ax = plt.subplots()
ax.imshow(df2.values, vmin=0, vmax=len(cmap.colors), cmap=cmap)


for i in range(len(df2)):
    for j in range(len(df2.columns)):
        ax.text(j,i, df.values[i,j], ha="center", va="center")
plt.show()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...