Цветовая шкала по строкам в Seaborn Heatmap - PullRequest
0 голосов
/ 30 января 2020

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

Это мой код:

sales = sales.pivot_table(index='Sources', columns='Category', values='Value')

sns.heatmap(sales,annot=True, cmap='coolwarm',fmt='g',linewidths=1,linecolor='black',).set_title('Sales')

И это тепловая карта, которую я получаю из этого

enter image description here

Ответы [ 2 ]

0 голосов
/ 30 января 2020

Используя pandas, чтобы разделить каждую строку по максимуму, мы получаем раскраску, где максимум темно-красный, а остальные столбцы зависят от их отношения к максимуму. Таким образом, столбец, почти равный максимуму, будет более легким тедом. Колонка с только половиной продаж будет окрашена в белый цвет. Столбец почти без продаж будет синим.

На цветной полосе указан процент по сравнению с максимумом для каждой строки.

import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
import random

sources = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
categories = [f'Cat {i}' for i in range(1, 5)]
data = [[s, c, random.randint(2, 50)] for s in sources for c in categories]
sales = pd.DataFrame(data, columns=['Sources', 'Category', 'Value'])

# create a dataframe grouped by Sources and Category
per_source_cat = sales.groupby(['Sources', 'Category']).agg({'Value': 'sum'})
# calculate the maximum for each source
max_per_source = sales.groupby(['Sources']).agg({'Value': 'max'})
# divide the sales of each source by the maximum for that source
per_source_cat = per_source_cat.div(max_per_source, level='Sources') * 100
# convert to a pivot table
per_source_cat = per_source_cat.pivot_table(index='Sources', columns='Category', values='Value')
# convert the sales to a compatible pivot table
sales = sales.pivot_table(index='Sources', columns='Category', values='Value')
sns.heatmap(per_source_cat, cmap='coolwarm', annot=sales, fmt='g', linewidths=1, linecolor='black', ).set_title('Sales')
plt.show()

example heatmap

В качестве альтернативы, предположим, что вы хотите покрасить самый высокий красный и самый низкий синий, независимо от того, близки они или нет. Тогда вычитание минимума и деление на разницу между максимумом и минимумом может определить раскраску. Полная равная строка вызывает деление на ноль, которое можно обработать, используя fillna.

# create a dataframe grouped by Sources and Category
per_source_cat = sales.groupby(['Sources', 'Category']).agg({'Value': 'sum'})
# calculate the maximum and minimum for each source
max_per_source = sales.groupby(['Sources']).agg({'Value': 'max'})
min_per_source = sales.groupby(['Sources']).agg({'Value': 'min'})
# subtract the minimum and divide by the difference between maximum and minimum
per_source_cat = (per_source_cat - min_per_source) / (max_per_source - min_per_source) * 100
# in the case of all equal, there will be a division by 0, set every value to 100 %
per_source_cat = per_source_cat.fillna(100.0)

plot lowest colored blue

Теперь цветовая шкала показывает 100% для самый высокий, 0% для самого низкого и остальные окрашены в пропорции.

0 голосов
/ 30 января 2020

Используя numpy.argsort, вы можете найти порядок значений в каждой строке. Использование результата в качестве основы для раскрашивания даст вам отображение для каждой строки.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
from matplotlib.ticker import FixedFormatter

data = np.random.randint(1,250, size=(10,6))
b = np.argsort(np.argsort(data, axis=1), axis=1)

im = plt.imshow(b, aspect="auto", cmap="coolwarm")
plt.colorbar(im, ticks=np.array([0.0, 0.5, 1.0])*b.max(), 
             format=FixedFormatter(["low", "middle", "high"]))

for i in range(data.shape[0]):
    for j in range(data.shape[1]):
        plt.text(j,i,data[i,j], ha="center", va="center")

plt.show()

enter image description here

...