静かなる名辞

pythonとプログラミングのこと


【python】pandasのgroupbyで結果をlistにする

 pandasのgroupbyを使って、平均や標準偏差を計算する方法は検索するとすぐ出てきます。

 ただ、「そういうの良いから、項目ごとに使いやすいイテレータにしてまとめてくれよ!」と思うときがありますよね。

>>> import pandas as pd
>>> df = pd.DataFrame({"A":[c for _ in range(5) for c in ["a", "b"]], "B":range(10)})
>>> df
   A  B
0  a  0
1  b  1
2  a  2
3  b  3
4  a  4
5  b  5
6  a  6
7  b  7
8  a  8
9  b  9
>>> df.groupby("A")
<pandas.core.groupby.DataFrameGroupBy object at 0x7fd0742ec4e0>  # よくわからない

 とりあえず愚直にlistにしてみます。

>>> list(df.groupby("A"))
[('a',    A  B
0  a  0
2  a  2
4  a  4
6  a  6
8  a  8), ('b',    A  B
1  b  1
3  b  3
5  b  5
7  b  7
9  b  9)]

 それぞれがデータフレームか。悪くはないけど、グルーピング対象の項目は要らないかな。

 というか、特定の列だけあれば良いシチュエーションの方が多いでしょう。

>>> list(df.groupby("A")["B"])
[('a', 0    0
2    2
4    4
6    6
8    8
Name: B, dtype: int64), ('b', 1    1
3    3
5    5
7    7
9    9
Name: B, dtype: int64)]

 けっこうそれらしくなってきた? 辞書にしてみましょう。

>>> dict(list(df.groupby("A")["B"]))["a"]
{'a': 0    0
2    2
4    4
6    6
8    8
Name: B, dtype: int64, 'b': 1    1
3    3
5    5
7    7
9    9
Name: B, dtype: int64}
>>> dict(list(df.groupby("A")["B"]))["a"]
0    0
2    2
4    4
6    6
8    8
Name: B, dtype: int64

 Seriesはそんなに好きになれないので、スマートなコードでリストにできないか……と思って検索したら、こんなのがありました。

python - grouping rows in list in pandas groupby - Stack Overflow

>>> df.groupby("A")["B"].apply(list)
A
a    [0, 2, 4, 6, 8]
b    [1, 3, 5, 7, 9]
Name: B, dtype: object


 なるほどねー。これで良いでしょう。df.groupby("A")["B"].apply(list)["a"]とかで取り出せるみたいだし。