Измените цвет отдельных ящиков на участках с пандой

1

Это относится к следующему вопросу, в котором обсуждаются варианты настройки заголовка и компоновки подзаголовков: изменение выходных данных pandas boxplot

Мое требование состоит в том, чтобы изменить цвета отдельных ящиков в каждом подзаголовке (как показано ниже):

Изображение 174551

Ниже приведен код, доступный по общей ссылке для настройки свойств заголовка и оси подзаголовков:

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

df = pd.DataFrame(np.random.rand(140, 4), columns=['A', 'B', 'C', 'D'])
df['models'] = pd.Series(np.repeat(['model1','model2', 'model3', 'model4',     'model5', 'model6', 'model7'], 20))
bp = df.boxplot(by="models",layout=(4,1),figsize=(6,8))
[ax_tmp.set_xlabel('') for ax_tmp in np.asarray(bp).reshape(-1)]
fig = np.asarray(bp).reshape(-1)[0].get_figure()
fig.suptitle('New title here')
plt.show()

Я попытался использовать свойство: ax.set_facecolor ('color'), но не удалось получить желаемый результат.

Я попытался получить доступ к bp ['boxes'], но, видимо, он недоступен. Мне нужно некоторое представление о структуре данных, хранящихся в bp, для доступа к отдельным ящикам в подзаголовке.

Жду с нетерпением

PS: Я знаю морского обитателя. Но нужно понимать и реализовывать с использованием df.boxplot в настоящее время. Спасибо

Теги:
pandas
dataframe
matplotlib
boxplot

2 ответа

2
Лучший ответ

Чтобы настроить цвета ваших полей в pandas.boxplot, вам нужно немного изменить свой код. Прежде всего, вы должны сказать boxplot чтобы на самом деле заполнить поля цветом. Вы делаете это, указав patch_artist = True, как patch_artist = True здесь. Однако кажется, что вы не можете указать цвет (по умолчанию синий) - пожалуйста, кто-нибудь меня исправит, если я ошибаюсь. Это означает, что вам нужно изменить цвет потом. К счастью, pandas.boxplot предлагает простой вариант, чтобы получить художников в boxplot как возвращаемое значение, указав return_type = 'both' увидеть здесь объяснение. Вы получаете pandas.Series с ключами в соответствии с вашими столбцами DataFrame и значениями, которые являются кортежами, содержащими экземпляры Axes на которых вырисовываются ящики, и фактические элементы ящиков в словаре. Я думаю, что код довольно понятен:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch

df = pd.DataFrame(np.random.rand(140, 4), columns=['A', 'B', 'C', 'D'])

df['models'] = pd.Series(np.repeat(['model1','model2', 'model3', 'model4',     'model5', 'model6', 'model7'], 20))

bp_dict = df.boxplot(
    by="models",layout=(4,1),figsize=(6,8),
    return_type='both',
    patch_artist = True,
)

colors = ['b', 'y', 'm', 'c', 'g', 'b', 'r', 'k', ]
for row_key, (ax,row) in bp_dict.iteritems():
    ax.set_xlabel('')
    for i,box in enumerate(row['boxes']):
        box.set_facecolor(colors[i])

plt.show()

Получившийся сюжет выглядит следующим образом:

Изображение 174551

Надеюсь это поможет.

  • 0
    Спасибо Томас :) Это было очень полезно. Просто упоминание, что я в итоге использовал bp_dict.iteritems (): когда я получал ошибку атрибута - «AttributeError: у объекта« Series »нет атрибута« items »»
  • 0
    Привет, Томас. Как сохранить независимую ось (y и x) для каждого подплота? Я использовал для i, el в enumerate (list (df.columns.values)): df.boxplot (el, by = metacategory, ax = axes.flatten () [i]), но не смог применить независимые цвета к каждая коробка в этом случае ...
Показать ещё 2 комментария
2

Хотя вы называете возврат df.boxplot bp, это действительно (n) (массив) осей. Проверка осей, чтобы получить отдельные части коробки, громоздка (но возможна).

Во-первых, чтобы иметь возможность раскрасить внутреннюю часть ящиков, вам нужно повернуть коробки на патчи, df.boxplot(..., patch_artist=True).

Тогда вам нужно будет найти ящики внутри всех художников в осях.

# We want to make the 4th box in the second axes red    
axes[1].findobj(matplotlib.patches.Patch)[3].set_facecolor("red")

Полный код:

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

df = pd.DataFrame(np.random.rand(140, 4), columns=['A', 'B', 'C', 'D'])
df['models'] = pd.Series(np.repeat(['model1', 'model2', 'model3', 'model4',
                                    'model5', 'model6', 'model7'], 20))
axes = df.boxplot(by="models", layout=(len(df.columns)-1,1), figsize=(6,8), patch_artist=True)

for ax in axes:
    ax.set_xlabel('')

# We want to make the 4th box in the second axes red    
axes[1].findobj(matplotlib.patches.Patch)[3].set_facecolor("red")

fig = axes[0].get_figure()
fig.suptitle('New title here')
plt.show()

Изображение 174551

  • 0
    Большое спасибо за ваш вклад :) Ваш ответ действительно помог мне лучше понять структуру. Оба ваших ответа были полезны и безупречны. Я принимаю ответ Томаса только для того, чтобы уважать тот факт, что он ответил на него первым. Я хотел бы принять оба варианта .. Большое спасибо еще раз. Кстати, я все еще в процессе обучения, какие-либо предложения о том, как самостоятельно следовать структуре переменной / назначения? Чтобы понять, к каким показателям обращаться? Еще раз спасибо. С уважением JALO
  • 0
    О, я не видел другого ответа. Вероятно, это лучше, потому что вам не нужно находить объекты на осях (это актуально, если у вас есть и другие объекты на осях). Не уверен, что я понимаю, что вы подразумеваете под "независимо следовать структуре переменной / присваивания".
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню