Pythonで集計(pandasライブラリをつかってみた)
Excelから取り込んだ売上データを顧客IDごとに集計して、別のExcelに出力するプログラム。
元ネタはこちら。
テキストP.177、「顧客ごとの売上額を集計する」
自分なりのロジックを検討してみた
プラン1
売上データを読み込みながら、新たに顧客idを見つけるたびに、動的に確保したリストに追加する。
読み込んだ顧客idがすでにリスト中に見つかった場合には、売上額を加算する。
売上データを読み終えたら、リストを別名で保存する。
プラン1の結果
最初の売上データを読み込んで、リストに追加するまでは順調。
だけれども、次の売上データを読み込んで、リストを舐めて同じ顧客idの有無を判定しようとするものの、メモリ上のリストはプログラム開始時点の空のリストとなっているようで、必ずヒット失敗となってしまう。
結果、入力データとおなじものを出力するので集計できない。
多分、対処の方法はあるんだろうけれども、、、わからん。
うーん、まいった。
pandasライブラリ
「python 集計処理」でググってみたら、世の中にはpandasという便利なライブラリがあることに気づく。早速インストールしてみた。
jm3nrhMac-mini-:~ akio$ pip3 install pandas
Collecting pandas
Downloading pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl.metadata (19 kB)
Collecting numpy>=1.26.0 (from pandas)
Downloading numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl.metadata (61 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 61.1/61.1 kB 3.2 MB/s eta 0:00:00
Collecting python-dateutil>=2.8.2 (from pandas)
Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting pytz>=2020.1 (from pandas)
Downloading pytz-2024.1-py2.py3-none-any.whl.metadata (22 kB)
Collecting tzdata>=2022.7 (from pandas)
Downloading tzdata-2024.1-py2.py3-none-any.whl.metadata (1.4 kB)
Collecting six>=1.5 (from python-dateutil>=2.8.2->pandas)
Downloading six-1.16.0-py2.py3-none-any.whl.metadata (1.8 kB)
Downloading pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl (11.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.3/11.3 MB 65.8 MB/s eta 0:00:00
Downloading numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl (13.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.7/13.7 MB 79.7 MB/s eta 0:00:00
Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 229.9/229.9 kB 19.2 MB/s eta 0:00:00
Downloading pytz-2024.1-py2.py3-none-any.whl (505 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 505.5/505.5 kB 35.7 MB/s eta 0:00:00
Downloading tzdata-2024.1-py2.py3-none-any.whl (345 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 345.4/345.4 kB 29.2 MB/s eta 0:00:00
Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: pytz, tzdata, six, numpy, python-dateutil, pandas
Successfully installed numpy-1.26.4 pandas-2.2.2 python-dateutil-2.9.0.post0 pytz-2024.1 six-1.16.0 tzdata-2024.1
jm3nrhMac-mini-:~ akio$
無事にインストールが出来た。
「顧客ごとの売上額を集計する」するコードがこちら
ライブラリのインポート指定を除くと、たったの3行!
import pandas as pd
df_in = pd.read_excel('売上データ_202007.xlsx', header=2)
df_out = df_in[["顧客ID", "顧客名称", "計"]].groupby(["顧客ID", "顧客名称"], as_index=False).sum()
df_out.to_excel('売上データ_202007_顧客別売上合計_akio.xlsx', sheet_name='顧客別売上', index=False)
エクセルファイルから、売上データの取り込み
PythonのIDLE環境の便利なところは、Shellウィンドウでコマンドを実行して結果をすぐに得られること。
何度かの試行錯誤の結果、次のコードで売上データを無事に取り込むことができた。
df_in = pd.read_excel('売上データ_202007.xlsx', header=2)
header=2としているのは、最初の行(0行目)にはファイル名、次(1行目)
がブランクで、2行目にやっとヘッダー情報が現れるため。
うまく取り込めているかは、以下で確認できる。(取り込んだ売上データの一覧が表示される。)
print(df_in)
売上データの集計
以下のパラメータの設定に辿り着くまで、四苦八苦しました。
df_out = df_in[["顧客ID", "顧客名称", "計"]].groupby(["顧客ID", "顧客名称"], as_index=False).sum()
備忘録を兼ねて、分解して説明します。
①集計対象となる3つの項目を指定。
df_in[["顧客ID", "顧客名称", "計"]]
②集計単位を指定。
最初、"顧客ID"だけ指定したらいいのではと思ったけど、["顧客ID", "顧客名称"]の両方を指定しないと、主計結果がグチャグチャになってしまいます。
.groupby(["顧客ID", "顧客名称"]
③インデックスをグルーピングされたくない場合は、groupbyにas_index=Falseを指定します。これをしておかないと、インデックスが表示されず、集計値だけの表示となってしまいます。
, as_index=False)
④集計が目的なので、sum()を指定。
他に、平均値や、最大値、最小値の計算を指定することも出来ます。
.sum()
集計済みのデータをエクセルファイルに出力
出力するエクセルのファイル名、シート名、そしてインデックスキーの出力抑止を指定します。
df_out.to_excel('売上データ_202007_顧客別売上合計_akio.xlsx', sheet_name='顧客別売上', index=False)
実行結果
jm3nrhMac-mini-:ch04 akio$ python3 xl_sum_sales_akio.py
jm3nrhMac-mini-:ch04 akio$
実務への応用
以上の機能は、ちょうどExcelのピボット集計を自動化したのと同等。
Excelだと、データの範囲の指定や、集計単位の設定などを手操作で行わないといけないけど、このプログラムで自動化できるのは、操作ミスを軽減したり、これらの作業に不慣れな人に集計作業を依頼することを考えるととても有意義かもしれない。
ここまで読んでいただき、ありがとうございました。
(冒頭の写真は、大津市の柳が崎湖畔公園のイングリッシュガーデンの壁一面の薔薇)