web-dev-qa-db-ja.com

a pandas DataFrameの複数の列を並べた箱ひげ図

1年間のサンプルデータ:

_import pandas as pd
import numpy.random as rnd
import seaborn as sns
n = 365
df = pd.DataFrame(data = {"A":rnd.randn(n), "B":rnd.randn(n)+1},
                  index=pd.date_range(start="2017-01-01", periods=n, freq="D"))
_

これらのデータを月ごとにグループ化して箱ひげ図にしたい(つまり、月に2つのボックス、1つはA用、もう1つはB用)。

単一の列の場合、sns.boxplot(df.index.month, df["A"])は正常に機能します。ただし、sns.boxplot(df.index.month, df[["A", "B"]])はエラーをスローします(_ValueError: cannot copy sequence with size 2 to array axis with dimension 365_)。 seabornのhueプロパティを回避策として使用するためにインデックス(pd.melt(df, id_vars=df.index, value_vars=["A", "B"], var_name="column"))でデータを溶かすことも機能しません(_TypeError: unhashable type: 'DatetimeIndex'_)。

(プレーンなmatplotlibを使用する方が簡単な場合、ソリューションは必ずしもseabornを使用する必要はありません。)

編集

基本的に私が欲しいものを生み出す回避策を見つけました。ただし、DataFrameにプロットしたいよりも多くの変数が含まれていると、操作がやや厄介になります。したがって、よりエレガントで直接的な方法がある場合は、共有してください。

_df_stacked = df.stack().reset_index()
df_stacked.columns = ["date", "vars", "vals"]
df_stacked.index = df_stacked["date"]
sns.boxplot(x=df_stacked.index.month, y="vals", hue="vars", data=df_stacked)
_

生産: Side-by-side boxplot of A and B, grouped by month.

10
Fred S

pandas融解と海生)を使用した解決策は次のとおりです。

import pandas as pd
import numpy.random as rnd
import seaborn as sns
n = 365
df = pd.DataFrame(data = {"A": rnd.randn(n),
                          "B": rnd.randn(n)+1,
                          "C": rnd.randn(n) + 10, # will not be plotted
                         },
                  index=pd.date_range(start="2017-01-01", periods=n, freq="D"))
df['month'] = df.index.month
df_plot = df.melt(id_vars='month', value_vars=["A", "B"])
sns.boxplot(x='month', y='value', hue='variable', data=df_plot)
1
_month_dfs = []
for group in df.groupby(df.index.month):
    month_dfs.append(group[1])

plt.figure(figsize=(30,5))
for i,month_df in enumerate(month_dfs):
    axi = plt.subplot(1, len(month_dfs), i + 1)
    month_df.plot(kind='box', subplots=False, ax = axi)
    plt.title(i+1)
    plt.ylim([-4, 4])

plt.show()
_

this を与えます

探しているものとは異なりますが、変数を追加すると、読み取り可能なDataFrameを維持できます。

を使用して軸を簡単に削除することもできます

_if i > 0:
        y_axis = axi.axes.get_yaxis()
        y_axis.set_visible(False)
_

plt.show()の前のループ内

0

Altair を使用すると、これは非常に簡単です。

alt.Chart(
    df.reset_index().melt(id_vars = ["index"], value_vars=["A", "B"]).assign(month = lambda x: x["index"].dt.month)
).mark_boxplot(
    extent='min-max'
).encode(
    alt.X('variable:N', title=''),
    alt.Y('value:Q'),
    column='month:N',
    color='variable:N'
)

enter image description here 上記のコードは、DataFrameを溶かし、month列を追加します。次に、Altairは、プロット列として月ごとに分類された各変数の箱ひげ図を作成します。

0
foglerit

私はあなたの質問を完全には理解していませんが、matplotlibを使用してこのアプローチを検討することをお勧めします。しかし、最善の解決策ではありません。

1)dfmonthsで12個のデータフレームに分割し、すべてリストに積み上げます

DFList = []
for group in df_3.groupby(df_3.index.month):
    DFList.append(group[1])

2)ループでそれらを次々にプロットします。

for _ in range(12):
    DFList[_].plot(kind='box', subplots=True, layout=(2,2), sharex=True, sharey=True, figsize=(7,7))

plt.show()

3)最初の3行のスナップショットは次のとおりです。

enter image description here

matplotlibの-​​ add_subplotメソッド もチェックアウトすることをお勧めします

0
benSooraj