Основной вопрос, по-видимому, заключается в том, как рассчитать координаты прямоугольника, окружающего каждый столбец.
Параметры Прямоугольник равны Rectangle((x, y), width, height, ...
При работе с По категориальным данным, позиция x каждого имени представляет собой индекс 0, 1, 2, ...
. Расстояние по x между двумя последовательными именами равно 1.0, поэтому немного меньшее число можно использовать в качестве ширины прямоугольника. Позиция x для имени находится в центре поля. Чтобы получить центрированный прямоугольник, мы можем расположить его по x минус половина ширины.
Для y-позиции и высоты мы можем взять пределы осей и вычесть некоторые отступы.
In код ниже некоторых случайных данных генерируется. Кроме того, размер фигуры устанавливается перед вызовом участков.
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
N = 100
raw_names = np.random.choice(['Amy', 'Jake', 'Jason', 'Molly', 'Tina'], N)
raw_scores = np.random.uniform(0, 95, N)
data = pd.DataFrame({'first_name':raw_names, 'pre_score': raw_scores})
order = np.sort(data['first_name'].unique())
save_images = r'D:\test'
plt.rcParams["figure.figsize"] = [18.0, 10.0]
for name_ind, x_names in enumerate(order):
np.random.seed(123456) # to get the same random stripplot everytime
sns.set_style("ticks")
ax = sns.stripplot(x='first_name', y='pre_score', hue='first_name', order=order, jitter=True, dodge=False, size=6, zorder=0, alpha=0.5, linewidth=1, data=data)
ax = sns.boxplot(x='first_name', y='pre_score', hue='first_name', order=order, dodge=False, showfliers=True, linewidth=0.8, showmeans=True,width=0.28, data=data)
ax = sns.pointplot(x='first_name', y='pre_score', order=order, data=data, ci=None, color='black')
ax.yaxis.set_tick_params(labelsize=14)
ax.xaxis.set_tick_params(labelsize=14)
ymin, ymax = plt.ylim()
height = ymax - ymin
width = 0.7
ax.add_patch(plt.Rectangle((name_ind - width / 2, ymin + height * 0.02), width, height * 0.96,
edgecolor='crimson', fill=False))
plt.legend(loc='upper left', title='', bbox_to_anchor=[1.01, 0, 1, 1])
plt.savefig(save_images+x_names+'.png', dpi=150, bbox_inches="tight")
plt.clf()
# plt.tight_layout(pad=2)
# plt.show()
![sample plot](https://i.stack.imgur.com/VhT9g.png)