如何适应第一个标签 matplotlib python 的第二个标签底部

How fit second label bottom of the first label matplolib python

我想在 matplotlib 的绘图中放置特定标记,例如第一个标签底部的第二个标签。 我的文件格式是这样的:

文件1.txt

3
4
6
.
.
etc

文件2.txt

5
12
8
.
.
etc

文件3.txt

230.45
345.65
342.3
.
.
etc.

我的脚本是这样的:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import unicode_literals
from numpy import *
from matplotlib.ticker import FormatStrFormatter
from matplotlib.ticker import MaxNLocator
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as tkr
import matplotlib.patches as patches

with open("1.txt") as f:
        lstx = [int(x) for x in f.read().split()]

with open("2.txt") as f:
            lsty = [int(x) for x in f.read().split()]

with open("3.txt") as f:
            lstz = [float(x) for x in f.read().split()]

def numfmt(x, pos):
    s = '{}'.format(int(x + 120))
    return s

def numfmty(y, pos):
    m = '{}'.format(int(y + 120))
    return m

       
x=np.array(lstx)
y=np.array(lsty)
z=np.array(lstz)
 
df = pd.DataFrame.from_dict(np.array([y,x,z]).T)
df.columns = ['X_value','Y_value','Z_value']
df['Z_value'] = pd.to_numeric(df['Z_value'])

fig, ax = plt.subplots(figsize=(11,9))

pivotted= df.pivot('X_value','Y_value','Z_value')

ax = sns.heatmap(pivotted, cmap='plasma_r', vmin=0.0, vmax=234.525)
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=20)
    
plt.gca().invert_yaxis()
xfmt = tkr.FuncFormatter(numfmt)
plt.gca().xaxis.set_major_formatter(xfmt)
yfmt = tkr.FuncFormatter(numfmty)
plt.gca().yaxis.set_major_formatter(yfmt)

plt.xlabel('\n Number', fontsize=24)
plt.ylabel('Number \n', fontsize=24)
plt.xticks(size=16)
plt.yticks(size=16)

plt.tight_layout()
major_ticks = np.arange(0, 33, 1)
minor_ticks = np.arange(0, 33, 1)
ax.set_xticks(major_ticks)
ax.set_xticks(minor_ticks, minor=True)
ax.set_yticks(major_ticks)
ax.set_yticks(minor_ticks, minor=True)
ax.grid(which='both')
ax.grid(which='minor', alpha=0.5)
ax.grid(which='major', alpha=0.5)

rect3 = patches.Rectangle((5,5),13,13,linewidth=1.7,linestyle='--',edgecolor='black',facecolor='none')

ax2 = ax.twiny()
ax2.xaxis.set_ticks_position("bottom")
ax2.xaxis.set_label_position("bottom")
newpos=[2,4,6]
newlabel=['*', '*', '*']
ax2.set_xticks(newpos)
ax2.set_xticklabels(newlabel)

ax.add_patch(rect3)
plt.grid()
plt.show()

我想在两个坐标轴的125、128、130、133、138、142、143位置打一个标记'*',大小为16。 当我尝试放置它们时,它们非常小,在第一个标签上并且网格正在移动。输出是这样的:

我怎么能适应呢?非常感谢

以下代码在指定的列和行中添加星号。

关于 seaborn 的一些令人困惑的是,它非常自以为是地优先考虑格式的外观,而不是过多地关心内部表示。例如,实际刻度位置在一半,但显示为整数。

请注意 plt.tight_layout() 最好是 plt.show() 之前的最后命令之一。另请注意,如果您事先创建了 ax,建议将其作为参数传递给 sns.heatmap()

在下面的代码中,主要刻度位于一半以定位刻度标签,而次要刻度位于整数位置以显示网格。

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

x = np.tile(np.arange(0, 33, dtype=int), 33)
y = np.repeat(np.arange(0, 33, dtype=int), 33)
z = np.random.randint(0, 50, len(x)).astype(float)
z[x == y] = np.nan
z[np.abs(x - y) == 1] = 200
z[np.abs(x - y) == 2] = 150

df = pd.DataFrame.from_dict({'X_value': x, 'Y_value': y, 'Z_value': z})
pivotted = df.pivot('X_value', 'Y_value', 'Z_value')

fig, ax = plt.subplots(figsize=(11, 9))

sns.heatmap(pivotted, cmap='plasma_r', vmin=0.0, vmax=234.525, square=True, ax=ax)
ax.invert_yaxis()
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=20)

ax.set_xlabel('\n Number', fontsize=24)
ax.set_ylabel('Number \n', fontsize=24)
major_tick_pos = np.arange(0.5, 33, 1)
special_ticks = [125, 128, 130, 133, 138, 142, 143]
major_tick_labels = [('★ ' if i + 120 in special_ticks else '') + f'{i + 120}' for i in range(33)]
minor_tick_pos = np.arange(0, 34, 1)
ax.set_xticks(major_tick_pos)
ax.set_xticks(minor_tick_pos, minor=True)
ax.set_xticklabels(major_tick_labels, size=16, rotation=90)
ax.set_yticks(major_tick_pos)
ax.set_yticks(minor_tick_pos, minor=True)
ax.set_yticklabels(major_tick_labels, size=16, rotation=0)

ax.grid(which='minor', color='black', ls=':', alpha=0.5, lw=2)
ax.tick_params(axis='both', length=0)
rect3 = patches.Rectangle((5, 5), 13, 13, linewidth=1.7, linestyle='--', edgecolor='black', facecolor='none')
ax.add_patch(rect3)
plt.tight_layout()
plt.show()

PS:如果你想要网格另一边的星星,twinx()twiny()都需要,只使用'★ ' if i + 120 in special_ticks else ''部分标签数。

另一种想法是在单元格内使用注释来标记特殊的行和列:


stars = [['☆' if x in special_ticks or y in special_ticks  else ''  for x in range(120, 153)] 
         for y in range(120, 153)]
sns.heatmap(pivotted, cmap='plasma_r', vmin=0.0, vmax=234.525,
            annot=stars, fmt='s', annot_kws={'size':20}, square=True, ax=ax)

要更改刻度标签颜色,方法可以是:

xticks = ax.set_xticklabels(major_tick_labels, size=16, rotation=90)
yticks = ax.set_yticklabels(major_tick_labels, size=16, rotation=0)
for t in xticks + yticks:
    if t.get_text().startswith('★'):
        t.set_color('crimson')