Как отобразить гистограмму для данных из тепловой карты
Нужно в виде гистограммы отобразить количество ненулевых ячеек в каждом столбце heatmap(r) при этом
- В гистограмме три столбца с наибольшей частотой заполненных ячеек должны быть выделены красным цветом, все остальные синим цветом.
- Гистограммы должна располагаться над тепловой картой, и отображение значений для оси - Х должны сохраниться.
Как это можно реализовать ?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(rc={'figure.facecolor':'white'})
columns = ['c1','c2','c3','c4']
d = [[1,2,10,11],[2,8,11,16],[7,8,10,15],[3,5,13,14],[10,11,12,13]]
df = pd.DataFrame(d, columns=columns)
maxValue = df.values.max()
r = (df
.stack()
.reset_index(name="col")
.assign(x=1)
.pivot_table(index="level_0", columns="col", values="x")
.reindex(range(1,maxValue+1), axis=1)
.fillna(0)
.astype("int8")
.rename_axis(None)
.rename_axis(None, axis=1))
print(r)
print(r.sum(axis=0)) #Отобразить в виде histogram над heatmap
sns.heatmap(r, cmap="Blues", cbar=False, square = True, linewidths=1, linecolor="k")
plt.tick_params(labelbottom=False, labeltop=True)
#sns.histplot(r)
plt.show()
Ответы (1 шт):
Автор решения: Daniil Loban
→ Ссылка
Решение без 1 пункта.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(rc={'figure.facecolor':'white'})
columns = ['c1','c2','c3','c4']
d = [[1,2,10,11],
[2,8,11,16],
[7,8,10,15],
[3,5,13,14],
[10,11,12,13]
]
df = pd.DataFrame(d, columns=columns)
maxValue = df.values.max()
r = (df
.stack()
.reset_index(name="col")
.assign(x=1)
.pivot_table(index="level_0", columns="col", values="x")
.reindex(range(1,maxValue+1), axis=1)
.fillna(0)
.astype("int8")
.rename_axis(None)
.rename_axis(None, axis=1))
fig, ax = plt.subplots(2, 1) # две строки одна колонка
arr = np.array(r.sum(axis = 0))
lenD = len(d) # количество строк в гистограмме
# подготовка массива для гистограммы
hist = [np.flatnonzero((arr - (lenD - i - 1)).clip(0, maxValue)) for i in range(lenD)]
dfHist = pd.DataFrame(hist)
rHist = (dfHist
.stack()
.reset_index(name="col")
.assign(x=1)
.pivot_table(index="level_0", columns="col", values="x")
.reindex(range(lenD), axis=0)
.reindex(range(maxValue), axis=1)
.fillna(0)
.astype("int8")
.rename_axis(None)
.rename_axis(None, axis=1))
sns.heatmap(rHist, cmap="Blues", cbar=False, square = True, linewidths=1, linecolor="k", ax=ax[0])
sns.heatmap(r, cmap="Blues", cbar=False, square = True, linewidths=1, linecolor="k", ax=ax[1])
plt.show()
Ниже вариант с изменениями для ручной расскраски столбцов
можно его вынести в функцию

for i in range(lenD):
rHist[9][i] -= 0.6 if rHist[9][i]==1 else 0
rHist[10][i] -= 0.6 if rHist[10][i]==1 else 0
rHist[1][i] -= 0.6 if rHist[1][i]==1 else 0
sns.heatmap(rHist, cmap=sns.color_palette("tab10", 8), cbar=False, square = True, linewidths=1, linecolor="k", ax=ax[0])
Если поиграть с маской будет еще лучше

for i in range(lenD):
rHist[9][i] -= 0.2 if rHist[9][i]==1 else 0
rHist[10][i] -= 0.2 if rHist[10][i]==1 else 0
rHist[1][i] -= 0.2 if rHist[1][i]==1 else 0
sns.heatmap(rHist, cmap=sns.color_palette("hls", 2), mask=(rHist==0), cbar=False, square = True, linewidths=1, linecolor="k", ax=ax[0])
