【Pandas】groupbyでキーによるグルーピングをして統計値を算出する方法[Pandas]

  • URLをコピーしました!

Pandas

前回、matplotlibで積み上げの折れ線グラフを作成する方法(plt.stackplot)を紹介しました。

今回、Pandasのgroupbyでキーによるグルーピングをして統計値を算出する方法を紹介します。

まずPandasのデータフレームをこんな感じで準備してみました。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(df)

実行結果
  alphabet  number  data
0        a       3   200
1        b       2   300
2        c       1   400
3        c       2   500
4        b       1   600
5        a       3   700
6        b       1   800
7        c       2   900
8        a       3  1000

今回はこれを使って、groupbyを試していきます。

それでは始めていきましょう。

groupbyの使い方

groupbyを使うには「データフレーム.groupby(キー).計算の関数」とします。

つまり先ほどのデータフレームで「alphabet」でグルーピングをして、それぞれのグループの総計を算出するには「df.groupby(“alphabet”).sum()」とします。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(df.groupby("alphabet").sum())

実行結果
          number  data
alphabet              
a              9  1900
b              4  1700
c              5  1800

これでalphabetが「a」の時のnumberの総計とdataの総計、また同じく「b」の時のnumberの総計とdataの総計、「c」の時のnumberの総計とdataの総計が算出されます。

上記の例では総和「.sum()」を使っていますが、他に平均値「.mean()」、最大値「.max()」、最小値「.min()」、標準偏差「.std()」、データ数「.count()」、統計値のまとめ「.describe()」などが使用できます。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(df.groupby("alphabet").sum())
print(df.groupby("alphabet").mean())
print(df.groupby("alphabet").max())
print(df.groupby("alphabet").min())
print(df.groupby("alphabet").std())
print(df.groupby("alphabet").count())
print(df.groupby("alphabet").describe())

実行結果
          number  data
alphabet              
a              9  1900
b              4  1700
c              5  1800
            number        data
alphabet                      
a         3.000000  633.333333
b         1.333333  566.666667
c         1.666667  600.000000
          number  data
alphabet              
a              3  1000
b              2   800
c              2   900
          number  data
alphabet              
a              3   200
b              1   300
c              1   400
           number        data
alphabet                     
a         0.00000  404.145188
b         0.57735  251.661148
c         0.57735  264.575131
          number  data
alphabet              
a              3     3
b              3     3
c              3     3
         number                                              data              \
          count      mean      std  min  25%  50%  75%  max count        mean   
alphabet                                                                        
a           3.0  3.000000  0.00000  3.0  3.0  3.0  3.0  3.0   3.0  633.333333   
b           3.0  1.333333  0.57735  1.0  1.0  1.0  1.5  2.0   3.0  566.666667   
c           3.0  1.666667  0.57735  1.0  1.5  2.0  2.0  2.0   3.0  600.000000   

                                                          
                 std    min    25%    50%    75%     max  
alphabet                                                  
a         404.145188  200.0  450.0  700.0  850.0  1000.0  
b         251.661148  300.0  450.0  600.0  700.0   800.0  
c         264.575131  400.0  450.0  500.0  700.0   900.0  

ただし計算対象のデータがその関数で計算できない場合はエラーとなりますので注意してください。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(df.groupby("number").sum())
print(df.groupby("number").mean())

実行結果
       alphabet  data
number               
1           cbb  1800
2           bcc  1700
3           aaa  1900
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pandas/core/groupby/groupby.py:1942, in GroupBy._agg_py_fallback(self, how, values, ndim, alt)
   1941 try:
-> 1942     res_values = self._grouper.agg_series(ser, alt, preserve_dtype=True)
   1943 except Exception as err:

(中略)

TypeError: agg function failed [how->mean,dtype->object]

複数の統計値を一度に算出

複数の統計値を一度に算出するには「.agg([統計値1, 統計値2, 統計値3…])」とします。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(df.groupby("alphabet").agg(["sum", "max", "min", "mean"]))

実行結果
         number                    data                       
            sum max min      mean   sum   max  min        mean
alphabet                                                      
a             9   3   3  3.000000  1900  1000  200  633.333333
b             4   2   1  1.333333  1700   800  300  566.666667
c             5   2   1  1.666667  1800   900  400  600.000000

groupby後のデータの中身

groupbyによりグルーピングした後のデータの中身を見てみましょう。

ただしgroupbyでグルーピングしたデータはオブジェクトとなっているため、そのままprint関数に渡しても中身は見えません。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(df.groupby("alphabet"))

実行結果
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x1173037f0>

そこで「*(アスタリスク)」を使ってアンパックします。

アスタリスクを使ったアンパックに関してはこちらの記事で紹介していますので良かったらどうぞ。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

print(*df.groupby("alphabet"))

実行結果
('a',   alphabet  number  data
0        a       3   200
5        a       3   700
8        a       3  1000) ('b',   alphabet  number  data
1        b       2   300
4        b       1   600
6        b       1   800) ('c',   alphabet  number  data
2        c       1   400
3        c       2   500
7        c       2   900)

これによるとgroupbyでグルーピングした後はタプルとしてそれぞれのキー毎に分類され、各列のデータが保存されているのが分かります。

そのためインデックスを指定すればグルーピングしたキー(インデックス「0」) 、データフレーム(インデックス「1」)が得られます。

import pandas as pd

df = pd.DataFrame()
df["alphabet"] = ["a", "b", "c", "c", "b", "a", "b", "c", "a"]
df["number"] = [3, 2, 1, 2, 1, 3, 1, 2, 3]
df["data"] = [200, 300, 400, 500, 600, 700, 800, 900, 1000]

for data in df.groupby("alphabet"):
    print(data[0])
    print(data[1])
    print(data[1]["number"])

実行結果
a
  alphabet  number  data
0        a       3   200
5        a       3   700
8        a       3  1000
0    3
5    3
8    3
Name: number, dtype: int64
b
  alphabet  number  data
1        b       2   300
4        b       1   600
6        b       1   800
1    2
4    1
6    1
Name: number, dtype: int64
c
  alphabet  number  data
2        c       1   400
3        c       2   500
7        c       2   900
2    1
3    2
7    2
Name: number, dtype: int64

次回はNumPyでndarrayを分割するsplit、array_split、hsplit、vsplit、dsplitを紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする