matplotlib 的对角线热图

Diagonal heatmap with matplotlib

我有一个从 Pandas 创建的热图,方法是这样的:

tukey = tukey.set_index('index')
 
fix,ax = plt.subplots(figsize=(12,6))
ax.set_title(str(date)+' '+ str(hour)+':'+'00',fontsize=14)
heatmap_args = {'linewidths': 0.35, 'linecolor': '0.5', 'clip_on': False, 'square': True, 'cbar_ax_bbox': [0.75, 0.35, 0.04, 0.3]}
sp.sign_plot(tukey, **heatmap_args)

我已尝试使用 seaborn 执行此操作,但未获得所需的输出:

# Generate a mask for the upper triangle
mask = np.triu(np.ones_like(tukey, dtype=bool))
# Set up the matplotlib figure
f, ax = plt.subplots(figsize=(12, 6))
# Generate a custom diverging colormap
cmap = sns.diverging_palette(230, 20, as_cmap=True)
# Draw the heatmap with the mask and correct aspect ratio
sns.heatmap(tukey, mask=mask, cmap=cmap, vmax=.3, center=0,
                square=True, linewidths=.5, cbar_kws={"shrink": .5})

如图所示,它仍然在应该被屏蔽的地方显示正方形,显然 cbar 不同。

我的问题是有没有不用seaborn的方法让它对角线化?或者至少只是为了摆脱重复部分?

编辑:我的数据框示例(tukey):

>>>     1_a    1_b      1_c     1_d      1_e    1_f
index
1_a     1.00    0.900  0.75      0.736    0.900  0.400
1_b     0.9000  1.000  0.72      0.715    0.900  0.508
1_c     0.756   0.342  1.000     0.005    0.124  0.034
1_d     0.736   0.715  0.900     1.000    0.081  0.030 
1_e     0.900   0.900  0.804     0.793    1.000  0.475
1_f     0.400   0.508  0.036     0.030    0.475  1.000

*我可能打错了,两条对角线应该是相等的。

编辑: 进口:

import scikit_posthocs as sp
import pandas as pd
import numpy as np
import statsmodels.api as sm
import scipy.stats as stats
from statsmodels.formula.api import ols

import matplotlib.pyplot as plt
import scipy.stats as stats

import seaborn as sns

scikit_posthocs' sign_plot() 似乎创建了一个 QuadMeshsns.heatmap 也是如此)。为这样的网格设置边缘颜色将显示网格的整个宽度和高度的水平和垂直线。为了使边缘在“空白”区域不可见,可以将它们着色为与背景相同(例如白色)。可以通过将它们的值设置为 NaN 来使单个单元格不可见,例如在下面的代码中。

删除一列和一行(例如 tukey.drop('1_f', axis=1, inplace=True)tukey.drop('1_a', axis=0, inplace=True)), 无助于使绘图变小一点,因为 sign_plot 会自动将它们添加回去。

import matplotlib.pyplot as plt
import scikit_posthocs as sp
import pandas as pd
import numpy as np
from io import StringIO

data_str = '''     1_a    1_b      1_c     1_d      1_e    1_f
1_a     1.00    0.900  0.75      0.736    0.900  0.400
1_b     0.9000  1.000  0.72      0.715    0.900  0.508
1_c     0.756   0.342  1.000     0.005    0.124  0.034
1_d     0.736   0.715  0.900     1.000    0.081  0.030 
1_e     0.900   0.900  0.804     0.793    1.000  0.475
1_f     0.400   0.508  0.036     0.030    0.475  1.000'''
tukey = pd.read_csv(StringIO(data_str), delim_whitespace=True)

cols = tukey.columns
for i in range(len(cols)):
    for j in range(i, len(cols)):
        tukey.iloc[i, j] = np.nan

fix, ax = plt.subplots(figsize=(12, 6))
heatmap_args = {'linewidths': 0.35, 'linecolor': 'white', 'clip_on': False, 'square': True,
                'cbar_ax_bbox': [0.75, 0.35, 0.04, 0.3]}
sp.sign_plot(tukey, **heatmap_args)
plt.show()