Как разместить прямоугольник для выделения категориальных данных? - PullRequest
0 голосов
/ 28 января 2020

Я хочу нарисовать прямоугольники вместе с категориальными значениями данных по оси X.

Некоторые сообщения похожи, но не те, которые я ищу.

matplotlib: как нарисовать прямоугольник на изображении

Построение фигур в Matplotlib через al oop

Странное поведение matplotlib plt.Rectangle

Это ожидаемые результаты; enter image description here

Я бы хотел переместить прямоугольник к каждому последующему значению x. И сохраните все изображения отдельно.

enter image description here

Код для приведенных выше графиков (с предварительным кодом для прямоугольников):

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt   

data = pd.DataFrame(raw_data, columns = ['first_name', 'pre_score'])

order = np.sort(data['first_name'].unique())

save_images = r'D:\test'

for x_names in order:

    print(x_names)

    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')
    fig_size = [18.0, 10.0]
    plt.rcParams["figure.figsize"] = fig_size
    ax.yaxis.set_tick_params(labelsize=14)
    ax.xaxis.set_tick_params(labelsize=14)

    plt.Rectangle((0, 0), 0.28, max(data['pre_score']), color="red");

    # ax.add_patch(plt.Rectangle(x_names, fill=False, linewidth=2.0))

    plt.savefig(save_images +x_names+'.png', dpi=150,bbox_inches="tight")

Получил это после @JohanC enter image description here

1 Ответ

2 голосов
/ 28 января 2020

Основной вопрос, по-видимому, заключается в том, как рассчитать координаты прямоугольника, окружающего каждый столбец.

Параметры Прямоугольник равны 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...