matplotlib 中子图的框架和文本问题

Frame and text issues for Subplots in matplotlib

我正在尝试在此水平条形图中的条形旁边获取文本: [1]: https://i.stack.imgur.com/jgcvj.png

不过,“Fullerton”这个名字好像在红色图的里面,但我想把它移到它外面。问题是我必须以相同的方式移动每年的所有文本,这会使一些名字非常正确。有没有办法手动移动“Fullerton”?

  1. 此外,我希望能够控制我想要包含“框架”的哪些部分。我使用了代码 axes[1].set(frame_on=False) 但删除了所有内容。我想要包含 x 轴线。

  2. 此外,我希望年份数字位于 y 刻度线的中间。

  3. 最后,我不确定我的子图如何不列出每一年的值(从 2000 年到 2020 年)。我希望它这样做,但它们只是每 5 年一次。我尝试了很多方法,例如 set_yticks,但似乎不起作用。

我的代码如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime as dt
import time
import itertools
from sklearn.linear_model import Ridge
import seaborn.apionly as sns
import numpy as np; np.random.seed(1)

Years = np.array([2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020])

S_scores = np.array([20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -18, 35, 36, 37, 38, 39])

A_scores = np.array([40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60])



A_presidents = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U"]
S_presidents = ["AA", "BB", "CC", "DD", "EE", "FF", "GG", "HH", "II", "JJ", "KK", "LL", "MM", "NN", "OO", "PP", "QQ", "RR", "SS", "TT", "UU"]


regression_A = pd.DataFrame({
    "Years": Years,
    "A_scores": A_scores
})

lr = Ridge()
lr.fit(regression_A[['A_scores']], regression_A['Years'])
Ridge(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=None,
   normalize=False, random_state=None, solver='auto', tol=0.001)

regression_S = pd.DataFrame({
    "Years": Years,
    "S_scores": S_scores
})

lr = Ridge()
lr.fit(regression_S[['S_scores']], regression_S['Years'])
Ridge(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=None,
   normalize=False, random_state=None, solver='auto', tol=0.001)


fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, sharex=False, figsize= (8,8))


A = axes[0].barh(Years, A_scores, align='center', color=np.where(A_scores < 0, 'red', 'green'))
axes[0].set_xlim(-40, 80)
axes[0].plot(regression_A["A_scores"], lr.coef_*regression_A['A_scores']+lr.intercept_, color='orange')
axes[0].plot(lr.coef_*regression_A['Years']+lr.intercept_, regression_A["Years"], color='purple')
axes[0].set_xlabel("A Score")
axes[0].set(frame_on=False)  # Remove all the framing
axes[0].yaxis.set_ticks_position('right')
axes[0].vlines  

S = axes[1].barh(Years, S_scores, align='center', color=np.where(S_scores < 0, 'red', 'green'))
axes[1].set_xlim(-40, 80)
axes[1].set_ylabel("Years")
axes[1].yaxis.set_label_position("right")

axes[1].set_xlabel("S Score")
axes[1].set(frame_on=False)  # Remove all the framing


axes[1].plot(regression_S["S_scores"], lr.coef_*regression_S['S_scores']+lr.intercept_, color='orange')
axes[1].plot(lr.coef_*regression_S['Years']+lr.intercept_, regression_S["Years"], color='purple')


rects2 = A.patches

for rect, label in zip(A, A_presidents):
    width = rect.get_width() + 2
    label_y_pos = rect.get_y() + (rect.get_height() / 2)
    axes[0].text(width, label_y_pos, s=label, color='blue')#, ha="right", va="top")


rects1 = S.patches

for rect, label in zip(S, S_presidents):
    width = rect.get_width() + 2
    label_y_pos = rect.get_y() + rect.get_height() / 2
    axes[1].text(width, label_y_pos, s=label, color='blue')#, ha="right", va="top")
   
###TRENDLINE CODE###
import statsmodels.api as sm

resA = stats.theilslopes(Years, A_scores, 0.90)
lsq_resA = stats.linregress(A_scores, Years)
resS = stats.theilslopes(Years, S_scores, 0.90)
lsq_resS = stats.linregress(S_scores, Years)

axes[0].plot(A_scores, resA[1] + resA[0] * A_scores, '--', color="black", label="Thiel-Sen Regression Line")`

axes[1].plot(S_scores, resS[1] + resS[0] * S_scores, '--', color="black", label="Thiel-Sen Regression Line")

plt.tight_layout()


S_presidents 只是一个包含每年名称的列表。 S_scores 也只是一个列表,其中包含每年的相关分数。

谢谢!

修改点数

  1. 字符串注释的位置 如果值为负,位置信息设置为0,则放在右边;如果0离y轴太近,可以通过改变数值任意改变。
  2. 图框控件 将框架控制设置为仅降低。
  3. 将年份刻度线居中 手动调整子图间距,关闭tight_layout().
  4. 的自动调整
  5. 设置y轴年份刻度从2010到2020 为 y 轴创建一个刻度间隔并为刻度设置符号。
fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True, sharex=False, figsize= (8,8))
fig.subplots_adjust(wspace=0.18) # update

A = axes[0].barh(Years, A_scores, align='center', color=np.where(A_scores < 0, 'red', 'green'))
axes[0].set_xlim(-40, 80)
axes[0].plot(regression_A["A_scores"], lr.coef_*regression_A['A_scores']+lr.intercept_, color='orange')
axes[0].plot(lr.coef_*regression_A['Years']+lr.intercept_, regression_A["Years"], color='purple')
axes[0].set_xlabel("A Score")
#axes[0].set(frame_on=False)  # Remove all the framing
axes[0].yaxis.set_ticks_position('right')
axes[0].vlines  
axes[0].spines['top'].set_visible(False) # update
axes[0].spines['left'].set_visible(False) # update
axes[0].spines['right'].set_visible(False) # update
axes[0].set_yticks(np.arange(2000,2021,1)) # update
axes[0].set_yticklabels(np.arange(2000,2021,1)) # update

S = axes[1].barh(Years, S_scores, align='center', color=np.where(S_scores < 0, 'red', 'green'))
axes[1].set_xlim(-40, 80)
axes[1].set_ylabel("Years")
axes[1].yaxis.set_label_position("right")

axes[1].set_xlabel("S Score")
#axes[1].set(frame_on=False)  # Remove all the framing
axes[1].spines['top'].set_visible(False) # update
axes[1].spines['left'].set_visible(False) # update
axes[1].spines['right'].set_visible(False) # update

axes[1].plot(regression_S["S_scores"], lr.coef_*regression_S['S_scores']+lr.intercept_, color='orange')
axes[1].plot(lr.coef_*regression_S['Years']+lr.intercept_, regression_S["Years"], color='purple')

rects2 = A.patches

for rect, label in zip(A, A_presidents):
    width = rect.get_width() + 2
    label_y_pos = rect.get_y() + (rect.get_height() / 2)
    axes[0].text(width, label_y_pos, s=label, color='blue')#, ha="right", va="top")


rects1 = S.patches

for rect, label in zip(S, S_presidents):
    width = rect.get_width() + 2
    if width < 0: # update
        width = 0 # update
    label_y_pos = rect.get_y() + rect.get_height() / 2
    axes[1].text(width, label_y_pos, s=label, color='blue')#, ha="right", va="top")
    
#plt.tight_layout() # update

plt.show()