Подтвердить что ты не робот

Группировка ящиков в морском дне, когда ввод данных является DataFrame

Я намерен построить несколько столбцов в pandas dataframe, все сгруппированы по другому столбцу, используя groupby внутри seaborn.boxplot. Здесь есть приятный ответ на аналогичную проблему в matplotlib matplotlib: Group boxplots, но учитывая тот факт, что seaborn.boxplot поставляется с опцией groupby, я думал, что это было бы намного проще сделать это в seaborn.

Здесь мы переходим к воспроизводимому примеру, который терпит неудачу:

import seaborn as sns
import pandas as pd
df = pd.DataFrame(
[
[2, 4, 5, 6, 1],
[4, 5, 6, 7, 2],
[5, 4, 5, 5, 1],
[10, 4, 7, 8, 2],
[9, 3, 4, 6, 2],
[3, 3, 4, 4, 1]
], columns=['a1', 'a2', 'a3', 'a4', 'b'])

#Plotting by seaborn
sns.boxplot(df[['a1','a2', 'a3', 'a4']], groupby=df.b)

То, что я получаю, это то, что полностью игнорирует параметр groupby:

Failed groupby

Если я делаю это с одним столбцом, он работает благодаря другому SO-запросу Seaborn groupby pandas Series:

sns.boxplot(df.a1, groupby=df.b)

seaborn that does not fail

Итак, я хотел бы получить все мои столбцы в одном сюжете (все столбцы имеют аналогичный масштаб).

EDIT:

Вышеупомянутый вопрос SO был отредактирован и теперь включает в себя "не чистый" ответ на эту проблему, но было бы неплохо, если бы у кого-то была лучшая идея для этой проблемы.

4b9b3361

Ответ 1

Как отмечают другие ответы, функция boxplot ограничена построением одиночного "слоя" ящиков, а параметр groupby действует только тогда, когда вход представляет собой Серию, и у вас есть вторая переменная, которую вы хотите для использования для хранения наблюдений в каждой коробке.

Однако вы можете выполнить то, что, как я думаю, вы надеетесь с помощью функции factorplot, используя kind="box". Но сначала вам нужно "растопить" образец данных в так называемый формат long-form или "tidy", где каждый столбец является переменной, и каждая строка является наблюдением:

df_long = pd.melt(df, "b", var_name="a", value_name="c")

Тогда это очень просто построить:

sns.factorplot("a", hue="b", y="c", data=df_long, kind="box")

enter image description here

Ответ 2

На самом деле это не лучше, чем ответ, который вы связали, но я думаю, что для достижения этого в морском море используется FacetGrid, поскольку параметр groupby определен только для Series, переданных функции boxplot.

Здесь некоторый код - pd.melt необходим, потому что (насколько я могу это сказать) отображение фасета может принимать только отдельные столбцы в качестве параметров, поэтому данные необходимо преобразовать в "длинный" формат.

g = sns.FacetGrid(pd.melt(df, id_vars='b'), col='b')
g.map(sns.boxplot, 'value', 'variable')

faceted seaborn boxplot

Ответ 3

Функция групповой группировки берет серию не DataFrames, поэтому она не работает.

Как работа, вы можете сделать это:

fig, ax = plt.subplots(1,2, sharey=True)
for i, grp in enumerate(df.filter(regex="a").groupby(by=df.b)):
    sns.boxplot(grp[1], ax=ax[i])

он дает: sns

Обратите внимание, что df.filter(regex="a") эквивалентно df[['a1','a2', 'a3', 'a4']]

   a1  a2  a3  a4
0   2   4   5   6
1   4   5   6   7
2   5   4   5   5
3  10   4   7   8
4   9   3   4   6
5   3   3   4   4

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

Ответ 4

Вы можете использовать непосредственно boxplot (я думаю, когда вопрос был задан, это было невозможно, но с версией seaborn > 0.6 это так).

Как объясняет @mwaskom, вы должны "расплавить" образец кадра данных в его "длинную форму", где каждый столбец является переменной, а каждая строка - наблюдением:

df_long = pd.melt(df, "b", var_name="a", value_name="c")

Тогда вы просто заговорите:

sns.boxplot(x="a", hue="b", y="c", data=df_long)

plot obtained with boxplot