来自一组列的Seaborn热图?

2024-09-29 17:10:49 发布

您现在位置:Python中文网/ 问答频道 /正文

需要用seaborn创建热图,但似乎无法实现或完全掌握如何实现

每个组件(行)都需要出现在热图上。左侧(y轴)应显示每个组件的EID。有很多,所以如果每10-20个只有1个被标记,那就好了。x轴上应为ROTATION1{}{}{}{},代表数据集的5列。这里的EXTRA列与热图无关

热图应表示的值为ROT{}{}或160-180之间以2分隔的任何数字(因此160{}{}等)

某些行对于所有列ROTATION1-ROTATION5都是空白的,但组件仍应包含在热图中(并且不显示颜色)

+--------+-------+-----------+-----------+-----------+-----------+-----------+
| EID    | EXTRA | ROTATION1 | ROTATION2 | ROTATION3 | ROTATION4 | ROTATION5 |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| AB1178 | POS   | FLIP      |           | STILL     | 172       |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| EC8361 | NEG   |           |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| QS7229 | POS   |           |           | 160       |           | ROT       |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| SE0447 | NEG   | ROT       | STILL     |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| YT5489 | NEG   |           |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| SZ2548 | NEG   | 164       |           |           | FLIP      |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| OT6892 | POS   | FLIP      |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| PL3811 | POS   |           |           |           | STILL     |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| WQ0893 | POS   |           |           | ROT       |           | 170       |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| TY3551 | NEG   | 160       | FLIP      |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| PC6466 | POS   |           | 180       | 176       |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| YH5912 | POS   |           |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| BK6245 | NEG   |           |           |           | STILL     |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| GQ2081 | POS   |           |           |           | 162       | FLIP      |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| GF8633 | NEG   |           |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| FJ4895 | NEG   |           | 174       |           | ROT       |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| YD2504 | POS   |           |           |           |           | 162       |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| RF3510 | POS   |           |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| PN6167 | NEG   |           | 168       | FLIP      |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| RB9747 | POS   | FLIP      |           | STILL     | 178       | STILL     |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| BQ0841 | NEG   |           | ROT       |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| HJ5187 | NEG   |           |           |           |           |           |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| BP2359 | POS   | 168       | STILL     |           |           | ROT       |
+--------+-------+-----------+-----------+-----------+-----------+-----------+
| FN6198 | POS   | ROT       |           |           | 172       | FLIP      |
+--------+-------+-----------+-----------+-----------+-----------+-----------+

我所尝试的:

df = pd.read_csv('DATA.csv')
df = pd.DataFrame(df, columns = ['EID', 'ROTATION1','ROTATION2', 'ROTATION3', 'ROTATION4', 'ROTATION5'])

in_range = list(range(160,181, 2))
direction = ['ROT', 'FLIP', 'STILL']
elements = direction + ([str(num) for num in num_range])

sensing = sns.load_dataset("df")
sensing = sensing.pivot("EID", ['EID', 'ROTATION1','ROTATION2', 'ROTATION3', 'ROTATION4', 'ROTATION5'], elements)

heatmap = sns.heatmap(sensing)

这不起作用,因为我认为“x轴”元素应该是列的形式,而不是多行的形式?如果有人能告诉我如何绕道那就太好了

需要结果:

右侧带有“颜色图例栏”的热图,以ROT{}{}和160-180之间的数字用2分隔。如果可能的话,按这个顺序。 如前所述,左边的y轴应该有EID,但实际的数据集大约有200行,因此每10或20行表示一行就可以了。 热图中应该有5列,每列代表ROTATION1ROTATION5

我没有经验,只是需要一点帮助

使用Python2.7和PANDAS 0.24.2以及seaborn 0.9.1


Tags: posdf组件热图stillfliprotneg
1条回答
网友
1楼 · 发布于 2024-09-29 17:10:49

首先,您需要将数据中的所有值转换为数字类型,int,例如:

replacements = {np.nan: 157, 'FLIP': 182, 'STILL': 184, 'ROT': 187}
inv_replacements = {value: key for key, value in replacements.items()}

df = pd.read_csv(r'data/data.csv')
df = df.drop('EXTRA', axis = 1).set_index('EID')
annot = df.values

df = df.replace(replacements).astype(int)
        ROTATION1  ROTATION2  ROTATION3  ROTATION4  ROTATION5
EID                                                          
AB1178        182        157        184        172        157
EC8361        157        157        157        157        157
QS7229        157        157        160        157        187
SE0447        187        184        157        157        157
YT5489        157        157        157        157        157
SZ2548        164        157        157        182        157
OT6892        182        157        157        157        157
PL3811        157        157        157        184        157
WQ0893        157        157        187        157        170
TY3551        160        182        157        157        157
PC6466        157        180        176        157        157
YH5912        157        157        157        157        157
BK6245        157        157        157        184        157
GQ2081        157        157        157        162        182
GF8633        157        157        157        157        157
FJ4895        157        174        157        187        157
YD2504        157        157        157        157        162
RF3510        157        157        157        157        157
PN6167        157        168        182        157        157
RB9747        182        157        184        178        184
BQ0841        157        187        157        157        157
HJ5187        157        157        157        157        157
BP2359        168        184        157        157        187
FN6198        187        157        157        172        182

然后,您应该将每个数值映射到相应的标签,并准备颜色映射:

values = list(replacements.values())
values.extend(list(range(160, 181, 2)))
values = sorted(values)
vmap = {value: str(value) if value not in inv_replacements.keys() else inv_replacements[value] for value in values}
n = len(vmap)
cmap = sns.color_palette('tab20', n)
cmap[0] = (1, 1, 1, 1)

我选择了'tab20'颜色映射,因为您需要15种不同的颜色,而这个颜色映射是one of the few,包含足够的颜色。
然后可以绘制热图:

ax = sns.heatmap(df, cmap = cmap, annot = annot, fmt = '')

最后,您需要调整颜色映射:

colorbar = ax.collections[0].colorbar
r = colorbar.vmax - colorbar.vmin
colorbar.set_ticks([colorbar.vmin + 0.5*r/(n) + r*i/(n) for i in range(n)])
colorbar.set_ticklabels(list(vmap.values()))

完整代码

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np


replacements = {np.nan: 157, 'FLIP': 182, 'STILL': 184, 'ROT': 187}
inv_replacements = {value: key for key, value in replacements.items()}

df = pd.read_csv(r'data/data.csv')
df = df.drop('EXTRA', axis = 1).set_index('EID')
annot = df.values

df = df.replace(replacements).astype(int)


values = list(replacements.values())
values.extend(list(range(160, 181, 2)))
values = sorted(values)
vmap = {value: str(value) if value not in inv_replacements.keys() else inv_replacements[value] for value in values}
n = len(vmap)
cmap = sns.color_palette('tab20', n)
cmap[0] = (1, 1, 1, 1)


ax = sns.heatmap(df, cmap = cmap, annot = annot, fmt = '')

colorbar = ax.collections[0].colorbar
r = colorbar.vmax - colorbar.vmin
colorbar.set_ticks([colorbar.vmin + 0.5*r/(n) + r*i/(n) for i in range(n)])
colorbar.set_ticklabels(list(vmap.values()))
 
plt.show()
  • 用于检查的带注释的热图:

    enter image description here

  • 无注释的热图:

    enter image description here


我不建议使用连续颜色映射:可能很难区分一个值和下一个值。
但是,如果需要,可以对所有值或仅对数字值使用连续颜色贴图。
(当然,您可以保留或删除批注)

  • colormap'plasma'仅用于数值,白色用于nans,RGB用于分类值:

    cmap = sns.color_palette('plasma', n - 4)
    cmap.insert(0, (1, 1, 1, 1))
    cmap.append((1, 0, 0, 1))
    cmap.append((0, 1, 0, 1))
    cmap.append((0, 0, 1, 1))
    

    enter image description here

  • colormap'plasma'用于所有值:

    cmap = sns.color_palette('plasma', n - 1)
    cmap.insert(0, (1, 1, 1, 1))
    

    enter image description here

相关问题 更多 >

    热门问题