Используя 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()
В качестве альтернативы, предположим, что вы хотите покрасить самый высокий красный и самый низкий синий, независимо от того, близки они или нет. Тогда вычитание минимума и деление на разницу между максимумом и минимумом может определить раскраску. Полная равная строка вызывает деление на ноль, которое можно обработать, используя 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)
Теперь цветовая шкала показывает 100% для самый высокий, 0% для самого низкого и остальные окрашены в пропорции.