お悩み女子毎月届くCSVをExcelで開いて、合計やピボットテーブルを作り直すのがつらい……Pythonなら楽になる?
PythonでCSVを集計すると、読み込みから合計・平均・店舗別の集計までを数行で書けます。使う道具は、追加のインストールが要らない標準の csv モジュールと、表のデータを扱う外部ライブラリの pandas の2つです。
同じ売上CSVを csv と pandas の両方で集計し、店舗別の合計とピボット表を出すまでを、動くコードつきで紹介します。載せているコードはWindows 11 と Python 3.12 で動くことを確かめています(pandas 3.0.2)。データはすべて練習用のダミーです。
- csv と pandas の違いと、選び方
- 標準の csv で出す合計・平均・店舗別の集計
- pandas の読み込み・groupby・ピボット表
- 集計前の空欄チェックと検算
- 文字コード・カンマ・空欄で止まったときの直し方
PythonでCSV集計|2つの道具と練習用データ
CSVの集計には標準の csv と pandas のどちらも使えます。Excelの操作にあてはめた違いを見てから、練習用のデータを用意します。
csvとpandasの違い
csv は Python に最初から入っていて、追加のインストールは要りません。pandas は外部のライブラリで、pip install pandas で入れます。Excelの操作にあてはめると、次のように書き分けます。
| Excelの操作 | csv で書くと | pandas で書くと |
|---|---|---|
| 合計(SUM) | sum(金額のリスト) | df[“金額”].sum() |
| 平均(AVERAGE) | 合計 ÷ 件数 | df[“金額”].mean() |
| 件数(COUNT) | len(rows) | len(df) |
| 店舗別の合計(SUMIF) | 辞書に金額を足していく | df.groupby(“店舗”)[“金額”].sum() |
| 店舗×商品の表(ピボットテーブル) | 二重の辞書で組む(長くなる) | pd.pivot_table(…) |
お悩み女子会社のPCにライブラリを入れていいのか、分からない……
なべくん入れられるか分からないうちは、標準の csv だけで試せます。次の章の csv 版から読んでください。
筆者は集計が合計と店舗別の2、3種類で決まっていれば csv、切り口を何度も変えて見たいなら pandas にします。csv は切り口を増やすたびにコードが長くなり、pandas は1行で書けます。その代わり、pandas は入れる手間がかかります。
練習用の売上CSV
練習には次の10行の売上データを使います。sales.csv の名前で、BOM付きUTF-8で保存します。BOM はファイルの先頭に付く文字コードの目印です。
日付,店舗,商品,数量,金額
2026-10-01,東京,ボールペン,10,1200
2026-10-01,大阪,ノート,4,1000
2026-10-02,東京,付箋,6,1080
2026-10-02,名古屋,ボールペン,5,600
2026-10-03,大阪,ボールペン,8,960
2026-10-03,東京,ノート,3,750
2026-10-04,名古屋,付箋,2,360
2026-10-04,大阪,付箋,5,900
2026-10-05,東京,ボールペン,7,840
2026-10-05,名古屋,ノート,6,1500
Python では BOM付きUTF-8 を utf-8-sig と書きます。この指定はBOMのないUTF-8のファイルも読めるので、迷ったらこちらを使います。
PythonでCSVを集計する方法|標準のcsvで合計・平均・店舗別
標準の csv だけで、全体の合計と平均、店舗別の合計を出します。まず、CSVを読み込むところから始めます。
合計・平均・最大の計算
金額の列だけをリストにして、sum() で合計します。平均は合計を件数で割ります。
import csv
with open("sales.csv", encoding="utf-8-sig", newline="") as f:
rows = list(csv.DictReader(f))
amounts = [int(r["金額"]) for r in rows]
if not amounts:
raise ValueError("データ行がありません")
total = sum(amounts)
print("合計:", f"{total:,}円")
print("平均:", f"{total / len(amounts):,.1f}円")
print("最大:", f"{max(amounts):,}円")
実行結果は次のとおりです。
合計: 9,190円
平均: 919.0円
最大: 1,500円
Excelで金額の列を SUM した値と、9,190円が一致するかを見ます。一致を確かめてから、店舗別の集計に進みます。
店舗別の合計
店舗ごとの合計は店舗名をキーにした辞書へ金額を足していきます。defaultdict(int) は、まだ入っていないキーを 0 から始める辞書です。
import csv
from collections import defaultdict
with open("sales.csv", encoding="utf-8-sig", newline="") as f:
rows = list(csv.DictReader(f))
totals = defaultdict(int)
counts = defaultdict(int)
for r in rows:
totals[r["店舗"]] += int(r["金額"])
counts[r["店舗"]] += 1
for store in totals:
avg = totals[store] / counts[store]
print(f"{store}: 合計{totals[store]:,}円 / {counts[store]}件 / 平均{avg:,.1f}円")
実行結果は次のとおりです。
東京: 合計3,870円 / 4件 / 平均967.5円
大阪: 合計2,860円 / 3件 / 平均953.3円
名古屋: 合計2,460円 / 3件 / 平均820.0円
表示される順番は、ファイルに店舗が初めて出てきた順です。店舗が増えても、CSVに行が増えるだけで、コードは変えずに動きます。
PythonでCSV集計|pandasで読み込みからピボット表まで
pandas は表を扱う外部ライブラリです。使う場合は作業用の仮想環境に準備し、同じCSVを read_csv で読み込みます。
合計・平均・店舗別の集計
合計と平均は列を選んで sum() や mean() を付けるだけです。店舗別は groupby で分けてから集計します。
import pandas as pd
df = pd.read_csv("sales.csv", encoding="utf-8-sig")
print("合計:", df["金額"].sum())
print("平均:", df["金額"].mean())
print(df.groupby("店舗")["金額"].agg(["sum", "mean", "count"]).round(1))
実行結果は次のとおりです。
合計: 9190
平均: 919.0
sum mean count
店舗
名古屋 2460 820.0 3
大阪 2860 953.3 3
東京 3870 967.5 4
groupby("店舗") は「店舗ごとに分ける」指定で、ExcelのSUMIFやピボットテーブルにあたります。切り口を変えるときは、groupby("商品")["数量"].sum() のように列名を替えるだけです。
csv版との違いは並び順です。pandas は店舗名を文字コードの順に並べ替えるので、名古屋・大阪・東京の順になり、五十音順でもCSVに出てきた順でもありません。元の順のままにしたいときは sort=False を付けます。
店舗と商品を並べるピボット表
店舗を行に、商品を列に並べた表はpivot_table で作ります。Excelのピボットテーブルと同じ形です。
import pandas as pd
df = pd.read_csv("sales.csv", encoding="utf-8-sig")
pv = pd.pivot_table(
df,
index="店舗", # 行にする列
columns="商品", # 列にする列
values="金額", # 集計する値
aggfunc="sum", # 集計の方法
fill_value=0, # 該当がない組み合わせは0にする
margins=True, # 合計の行と列を足す
margins_name="合計",
)
print(pv)
実行結果は次のとおりです。
商品 ノート ボールペン 付箋 合計
店舗
名古屋 1500 600 360 2460
大阪 1000 960 900 2860
東京 750 2040 1080 3870
合計 3250 3600 2340 9190
index が行、columns が列、values が集計する値、aggfunc が集計の方法です。margins=True で、最後に合計の行と列が付きます。右下の9190がさきほどの全体の合計と一致しています。
PythonでCSV集計の注意点|文字コード・カンマ・空欄・検算
CSV集計では、データの形が原因で止まったり、結果がずれたりします。代表的な3つのつまずきと、検算の方法を順に見ます。
文字コードのエラー
cp932(Shift_JIS系)で保存されたCSVを UTF-8 として読むと、次のエラーで止まります。
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 0: invalid start byte
「UTF-8として読もうとしたが、先頭のバイトが読めない」という意味です。encoding="cp932" に変えると読めます。
カンマ付きの金額
金額が "1,200" のようにカンマ付きで入っているCSVでは、カンマを含む値が引用符で囲まれています。このまま int() にかけると、カンマが数として読めず、次のエラーで止まります。
ValueError: invalid literal for int() with base 10: '1,200'
直し方は数に直す前にカンマを取ることです。int(r["金額"].replace(",", "")) と書きます。pandas は read_csv に thousands="," を付けると、金額が int64 で読まれます。
空欄の扱い
金額が空欄の行があると、csv では int("") が次のエラーで止まります。
ValueError: invalid literal for int() with base 10: ''
pandas は止まらずに、空欄を欠損値(NaN)として読みます。その結果を見ます。
次の例は別のCSV sales_blank.csv を用意して確認します。列は金額だけで、データ行を1200、空欄、360の順にします。空欄の行はCSV上で "" と書けば読み飛ばされません。
import pandas as pd
df = pd.read_csv("sales_blank.csv", encoding="utf-8-sig")
print("空欄の数:", df["金額"].isna().sum())
print("合計:", df["金額"].sum())
print("平均(空欄を除く):", df["金額"].mean())
print("平均(空欄を0とする):", df["金額"].fillna(0).mean())
実行結果は次のとおりです。
空欄の数: 1
合計: 1560.0
平均(空欄を除く): 780.0
平均(空欄を0とする): 520.0
合計は空欄を飛ばして計算されます。平均は空欄を除くと780、0として数えると520になり、結果が変わります。どちらにするかは、集計の目的に合わせて人が決めます。
合計の検算
集計したら、結果が元のデータと合っているかを確かめます。見る点は2つです。店舗別の合計を足すと全体の合計になること。そして、全体の合計と行数が、Excelで開いたCSVの SUM・行数と同じになることです。
csv版なら、sum(totals.values()) == total が True になるかを見ます。この記事のデータでは True でした。行数はExcelの行数から見出しの1行を引いた数と一致します。一致しないときは、空欄や重複の行がないかを先に疑います。
PythonのCSV集計|よくある質問
道具の選び方と、複数のCSVをまとめるときの順序を確認します。
- csvとpandasは、どちらから覚えればよいですか?
-
会社のPCにライブラリを入れられるかで決めます。入れられるなら pandas のほうが短く書けます。入れられないときや、集計が合計と店舗別だけなら、標準の csv で足ります。どちらも結果をExcelの SUM と突き合わせて確かめます。
- 複数のCSVをまとめて集計するには?
-
各CSVの列名と金額の単位をそろえ、1つの表として集計します。まず1ファイルで合計を確かめ、その後に入力を増やす順が追いやすいです。同じCSVの二重取り込みにも注意します。
まとめ|PythonのCSV集計は、読み込みと検算を丁寧に
PythonでCSVを集計するポイントを整理します。
道具の選び方:追加のインストールなしなら csv、切り口を変えながら見るなら pandas。
csvでの集計:値は文字列で読まれるので int() で数にし、sum() と defaultdict で合計する。
pandasでの集計:read_csv で読み、groupby と pivot_table で集計する。元の順なら sort=False を指定する。
注意点:encoding を毎回書く。カンマと空欄は、数に直す前に確かめる。
検算:店舗別を足して全体と合うか、Excelの SUM と合うかを見る。
まずは手元のCSVで、金額の列の合計を1つ出して、ExcelのSUMと合うかを見るところから始めてみてください。
集計の前後に使う処理は次の記事でも扱っています。
参考資料
csv | Python 3 ドキュメント
codecs(utf-8-sig の説明) | Python 3 ドキュメント
pandas.read_csv | pandas ドキュメント
pandas.DataFrame.groupby | pandas ドキュメント
pandas.pivot_table | pandas ドキュメント
