问题描述
我想将特定标记(例如第一个标签的第二个标签底部)放在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。 当我尝试放置它们时,它们很小,位于第一个标签的上方,并且网格正在移动它。输出是这样的:
解决方法
以下代码在指示的行和列中添加星号。
让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()
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')