【问题标题】:How fit second label bottom of the first label matplolib python如何适合第一个标签matplotlib python的第二个标签底部
【发布时间】:2020-09-19 02:36:09
【问题描述】:

我想将特定标记(例如第一个标签底部的第二个标签)放在 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。 当我尝试放置它们时,它们非常小,位于第一个标签之上,并且网格正在移动它。输出是这样的:

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

【问题讨论】:

    标签: python matplotlib plot marker axis-labels


    【解决方案1】:

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

    关于 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')
    

    【讨论】:

    • 非常感谢!这就是我要找的。我有最后一个问题,如果我想要有颜色的星星,我尝试使用 ax.set_yticklabels(major_tick_labels, size=16, rotation=0, color='red'),但数字也是颜色。在这种情况下,我必须做其他只读取星星的变量吗?谢谢
    • 参见例如this post 关于彩色标签。让它为刻度标签工作更加棘手。 (我编辑发布了一种更改刻度标签颜色的方法,但每个标签只有一种颜色)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多