如何将第一个标签的第二个标签底部拟合为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','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,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,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。 当我尝试放置它们时,它们很小,位于第一个标签的上方,并且网格正在移动它。输出是这样的:

enter image description here

我怎么适应呢?非常感谢

解决方法

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

让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)
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,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,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,linewidth=1.7,linestyle='--',edgecolor='black',facecolor='none')
ax.add_patch(rect3)
plt.tight_layout()
plt.show()

resulting plot

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,annot=stars,fmt='s',annot_kws={'size':20},ax=ax)

要更改刻度标签的颜色,可以采用以下方法:

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...