MENU

PythonでCSV集計|合計・平均とpandasの基本

当ページのリンクには広告(PR)が含まれていることがあります。
PythonでCSVを集計する基本|合計・平均・グループ化の最小コードのアイキャッチ
お悩み女子

毎月届く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のファイルも読めるので、迷ったらこちらを使います。

手元のCSVで試すときは、列名(日付・店舗・商品・数量・金額)を自分のものに読み替えます。文字コードが合わずに止まったときは、後半の「文字コードのエラー」を見てください。

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" に変えると読めます。

どちらの文字コードか分からないときは、utf-8-sig と cp932 を順に試し、日本語が正しく表示されるほうに決めます。pandas の read_csv でも、encoding を同じように指定します。

カンマ付きの金額

金額が "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になり、結果が変わります。どちらにするかは、集計の目的に合わせて人が決めます。

pandas は止まらないぶん、空欄に気づきにくいのが落とし穴です。読み込んだら、isna().sum() で空欄の数を確かめてから集計します。

合計の検算

集計したら、結果が元のデータと合っているかを確かめます。見る点は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 ドキュメント

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次