【Python】pandasの集計の備忘

テーマはPythonのPandasでのデータ集計 pythonの話

Pythonのpandasで集計をした備忘です。
groupbyで集計するのにある列は合計、ある列は平均というように、集計列によって異なる集計方法で集計した備忘です。

pandasで複数の列でグルーピングして列によって違う集計

google先生で検索してもなかなかでてこなかったので備忘で残すことにしました。

やりたいことは

  • 複数の列でグルーピングする。(得意先別、商品群別みたいに集計)
  • 集計する値は列によって違う(単価列は平均、売上高は合計など)

検索しても、「複数列でグルーピングして集計はすべて同じ合計など」や「グルーピングは一列だけで集計は列によって変える」というのはすぐに見つかったのですが、両方を組み合わせたものは見つからなかったのでまとめたものをやってみました。

元のデータはこんな感じです。

import pandas as pd

#ヘッダーありのCSVを取り込む(header=0でヘッダー有りを指定)
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

print(df)
'''
      伝票番号        日付    得意先     品名   数量    単価      売上
0   100001  2023/1/1   東京商事   Tシャツ  100  1500  150000
1   100002  2023/1/1   東京商事  ポロシャツ   50  2100  105000
2   100003  2023/1/1  神奈川商会   Tシャツ   60  1400   84000
..     ...       ...    ...    ...  ...   ...     ...
16  100017  2023/1/7  神奈川商会   Tシャツ   80  1600  128000
17  100018  2023/1/7  神奈川商会  ポロシャツ   20  2000   40000
18  100019  2023/1/8   群馬商店   Tシャツ   10  1500   15000

[19 rows x 7 columns]
'''

「.groupby」を使って集計する

得意先で集計する

まずは、ひとつの項目を集計をしてみます。
得意先別に数量と売上の平均を集計します。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ndf = df.groupby(['得意先'])[["数量", "売上"]].mean()
print(ndf)
'''
              数量             売上
得意先                            
千葉商店   97.500000  251625.000000
東京商事   75.000000  127500.000000
神奈川商会  75.714286  160414.285714
群馬商店   56.666667   96250.000000
'''

複数の列で集計する

得意先別、商品別を集計対象にして、数量と売上の平均を集計してみます。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ndf = df.groupby(['得意先','品名'])[["数量", "売上"]].mean()
print(ndf)
'''
                     数量        売上
得意先   品名                         
千葉商店  Tシャツ    70.000000  108500.0
      トレーナー  120.000000  365000.0
      ポロシャツ   80.000000  168000.0
東京商事  Tシャツ   100.000000  150000.0
      ポロシャツ   50.000000  105000.0
神奈川商会 Tシャツ    63.333333  104000.0
      トレーナー   60.000000  180450.0
      ポロシャツ  110.000000  225000.0
群馬商店  Tシャツ    52.500000   76625.0
      ポロシャツ   65.000000  135500.0
'''

集計を単価は平均、数量・売上は合計で集計する。

先ほどと同様集計は「得意先別・商品別」で、集計方法を複数にしてみます。
単価は平均、数量と売上は合計を集計します。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ndf = df.groupby(['得意先','品名']).agg({"単価":"mean","数量": "sum", "売上": "sum"})
print(ndf)
'''
                      単価   数量      売上
得意先   品名                             
千葉商店  Tシャツ   1550.000000   70  108500
      トレーナー  3025.000000  240  730000
      ポロシャツ  2100.000000   80  168000
東京商事  Tシャツ   1500.000000  100  150000
      ポロシャツ  2100.000000   50  105000
神奈川商会 Tシャツ   1666.666667  190  312000
      トレーナー  3015.000000  120  360900
      ポロシャツ  2025.000000  220  450000
群馬商店  Tシャツ   1462.500000  210  306500
      ポロシャツ  2125.000000  130  271000
'''

売上は合計と件数を集計したい

groupbyだけじゃうまくいかない

「groupby」で売上を「”売上”: “sum”, “売上”:”count」で集計しようとすると、上手くいきませんでした。
後に記載したデータ個数だけが集計されます。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ndf = df.groupby(['得意先','品名']).agg({"単価":"mean","数量": "sum", "売上": "sum", "売上":"count"})
print(ndf)
'''
                      単価   数量  売上
得意先   品名                         
千葉商店  Tシャツ   1550.000000   70   1
      トレーナー  3025.000000  240   2
      ポロシャツ  2100.000000   80   1
東京商事  Tシャツ   1500.000000  100   1
      ポロシャツ  2100.000000   50   1
神奈川商会 Tシャツ   1666.666667  190   3
      トレーナー  3015.000000  120   2
      ポロシャツ  2025.000000  220   2
群馬商店  Tシャツ   1462.500000  210   4
      ポロシャツ  2125.000000  130   2
'''

同じ列を複数回集計したいときは列の追加で対応

売上は合計とデータ個数を集計したいときは、groupbyで合計で集計した後で、列を追加して売上のデータ個数を追加します。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ndf = df.groupby(['得意先','品名']).agg({"単価":"mean","数量": "sum", "売上": "sum"})
ndf['売上個数'] =  df[['売上']].groupby([df['得意先'],df['品名']]).count()
print(ndf)
'''
                      単価   数量      売上  売上個数
得意先   品名                                   
千葉商店  Tシャツ   1550.000000   70  108500     1
      トレーナー  3025.000000  240  730000     2
      ポロシャツ  2100.000000   80  168000     1
東京商事  Tシャツ   1500.000000  100  150000     1
      ポロシャツ  2100.000000   50  105000     1
神奈川商会 Tシャツ   1666.666667  190  312000     3
      トレーナー  3015.000000  120  360900     2
      ポロシャツ  2025.000000  220  450000     2
群馬商店  Tシャツ   1462.500000  210  306500     4
      ポロシャツ  2125.000000  130  271000     2
'''

「.pivot_table」を使って集計できる

pandasでは、「.pivot_table」を使っても集計ができます。
index、values、aggfuncには、リスト形式でそれぞれ複数の項目を設定できます。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ptdf = df.pivot_table(index=['得意先','品名'],  values=["数量","売上"], aggfunc=["sum","mean"],fill_value=0)
print(ptdf)
'''
                sum         mean            
                 売上   数量      売上          数量
得意先   品名                                    
千葉商店  Tシャツ   108500   70  108500   70.000000
      トレーナー  730000  240  365000  120.000000
      ポロシャツ  168000   80  168000   80.000000
東京商事  Tシャツ   150000  100  150000  100.000000
      ポロシャツ  105000   50  105000   50.000000
神奈川商会 Tシャツ   312000  190  104000   63.333333
      トレーナー  360900  120  180450   60.000000
      ポロシャツ  450000  220  225000  110.000000
群馬商店  Tシャツ   306500  210   76625   52.500000
      ポロシャツ  271000  130  135500   65.000000
'''

pandasの集計のあれこれ

集計の方法で主なものは以下の通りです。

'''
mean  平均
median 中央値
mode  最頻値
sum   合計
max  最大値
min  最小値
count データ数
std 標準偏差
var 分散
'''

CSVに書き出すときは、「.to_csv」で出力できます。
エクセルで使いたいときは、「encoding=”utf-8_sig”」というように「_sig」を追加しておくと文字化けしないです。

import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8", header=0)

ptdf = df.pivot_table(index=['得意先','品名'],  values=["数量","売上"], aggfunc=["sum","mean"],fill_value=0)
print(ptdf)ptdf.to_csv("pd_output.csv", encoding="utf-8_sig")

元データ全件

大したデータではないですが、全行を貼り付けておきます。これをExcelに貼り付けてCSVにすれば、上記を再現できるはずです。

伝票番号 日付 得意先 品名 数量 単価 売上
100001 2023/1/1 東京商事 Tシャツ 100 1500 150000
100002 2023/1/1 東京商事 ポロシャツ 50 2100 105000
100003 2023/1/1 神奈川商会 Tシャツ 60 1400 84000
100004 2023/1/2 千葉商店 トレーナー 40 3000 120000
100005 2023/1/3 千葉商店 ポロシャツ 80 2100 168000
100006 2023/1/3 神奈川商会 ポロシャツ 200 2050 410000
100007 2023/1/3 群馬商店 Tシャツ 50 1450 72500
100008 2023/1/3 千葉商店 トレーナー 200 3050 610000
100009 2023/1/3 群馬商店 ポロシャツ 100 2050 205000
100010 2023/1/3 神奈川商会 Tシャツ 50 2000 100000
100011 2023/1/4 群馬商店 Tシャツ 60 1400 84000
100012 2023/1/5 神奈川商会 トレーナー 30 3030 90900
100013 2023/1/5 千葉商店 Tシャツ 70 1550 108500
100014 2023/1/5 神奈川商会 トレーナー 90 3000 270000
100015 2023/1/5 群馬商店 ポロシャツ 30 2200 66000
100016 2023/1/6 群馬商店 Tシャツ 90 1500 135000
100017 2023/1/7 神奈川商会 Tシャツ 80 1600 128000
100018 2023/1/7 神奈川商会 ポロシャツ 20 2000 40000
100019 2023/1/8 群馬商店 Tシャツ 10 1500 15000

コメント

タイトルとURLをコピーしました