3日目のゴール
3日目のテーマは
「CSVを“ただ読む・書く”から一歩進めて、“集計・ソート・レポート作成”までできるようになること」 です。
1日目で「reader / writer」、
2日目で「DictReader / DictWriter」を押さえました。
今日はそこに、
合計・平均などの集計
条件付きの集計(例:30歳以上だけ)
CSVの内容を並び替えて別ファイルに出力
といった「実務データ処理の一歩目」を乗せていきます。
今日使うサンプルCSVを決めておく
people.csv を少し“仕事寄り”にする
3日目では、少しだけ実務寄りのデータを使います。
例えば、こんな employees.csv を用意したとします。
id,name,age,department,salary
1,Taro,25,Sales,300000
2,Hanako,30,HR,320000
3,Ken,22,Sales,250000
4,Naomi,35,Engineering,400000
5,Shin,28,Engineering,380000
ここでのポイントは、
「数値(age, salary)と文字列(name, department)が混ざっている」
ということです。
実務データはだいたいこういう形なので、
これを題材にしていきます。
基本の読み込み DictReader で辞書として扱う
まずは「1行=辞書」の感覚を再確認
最初に、employees.csv を DictReader で読み込んで、
中身をそのまま表示してみます。
import csv
def show_employees_raw():
with open("employees.csv", "r", encoding="utf-8", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
print(row)
show_employees_raw()
Python出力イメージはこうなります。
{'id': '1', 'name': 'Taro', 'age': '25', 'department': 'Sales', 'salary': '300000'}
{'id': '2', 'name': 'Hanako', 'age': '30', 'department': 'HR', 'salary': '320000'}
...
ここで改めて押さえたいのは、
CSVの1行が「キー: 文字列」の辞書として扱える
列名(id, name, age, department, salary)がそのままキーになっている
ということです。
この「列名でアクセスできる」状態が、
集計やソートの土台になります。
数値列をちゃんと「数値」として扱う
文字列のままだと計算できない
DictReader が返してくれる値は、
すべて「文字列」です。
例えば、row["salary"] は "300000" という文字列です。
このままでは、足し算や平均ができません。
そこで、
「数値として扱いたい列は、必ず int や float に変換する」
という習慣をつけます。
import csv
def show_employees_with_cast():
with open("employees.csv", "r", encoding="utf-8", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
age = int(row["age"])
salary = int(row["salary"])
print(f"{row['name']} さんは {age} 歳、給与は {salary} 円です。")
Pythonここでの重要ポイントは、
row["age"] や row["salary"] を、そのまま計算に使わない
必ず int() で整数に変換してから使う
ということです。
この一手間が、
「文字列のまま計算してバグる」事故を防いでくれます。
全社員の給与の合計と平均を出す
「合計」と「件数」を同時に数える
まずは、全社員の給与の合計と平均を出してみます。
import csv
def calc_total_and_average_salary():
with open("employees.csv", "r", encoding="utf-8", newline="") as f:
reader = csv.DictReader(f)
total_salary = 0
count = 0
for row in reader:
salary = int(row["salary"])
total_salary += salary
count += 1
if count == 0:
print("社員データがありません。")
return
average_salary = total_salary / count
print(f"社員数: {count} 人")
print(f"給与合計: {total_salary} 円")
print(f"給与平均: {average_salary:.1f} 円")
Pythonここで深掘りしたいポイントは三つです。
一つ目は、total_salary と count をループの外で 0 に初期化していること。
二つ目は、ループの中で「給与を足しながら、件数も1ずつ増やしている」こと。
三つ目は、ループが終わったあとで「合計 ÷ 件数」で平均を出していること。
このパターンは、
「何かの合計と平均を出したいときの基本形」
として、ぜひ体に染み込ませてほしいところです。
条件付き集計 30歳以上の平均給与を出す
if を挟むだけで「条件付き」に変わる
次は、「30歳以上の社員だけの平均給与」を出してみます。
やることは、さっきとほぼ同じです。
違うのは「if で条件を挟む」だけです。
import csv
def calc_average_salary_over_30():
with open("employees.csv", "r", encoding="utf-8", newline="") as f:
reader = csv.DictReader(f)
total_salary = 0
count = 0
for row in reader:
age = int(row["age"])
salary = int(row["salary"])
if age >= 30:
total_salary += salary
count += 1
if count == 0:
print("30歳以上の社員がいません。")
return
average_salary = total_salary / count
print(f"30歳以上の社員数: {count} 人")
print(f"30歳以上の給与平均: {average_salary:.1f} 円")
Pythonここでの重要ポイントは、
「集計の対象にするかどうか」を if で決めていること
条件を満たしたときだけ、合計と件数を増やしていること
つまり、
「集計の基本形+if 条件」=条件付き集計
という構造になっています。
部署ごとの給与合計・平均を出す
「グループごとに集計する」という発想
実務でよくあるのが、
「部署ごとに集計したい」というニーズです。
例えば、
Sales / HR / Engineering ごとに
給与の合計と平均を出したい、というケースです。
ここでは、
「部署名をキーにした辞書」を使います。
import csv
def calc_salary_by_department():
with open("employees.csv", "r", encoding="utf-8", newline="") as f:
reader = csv.DictReader(f)
stats = {}
for row in reader:
dept = row["department"]
salary = int(row["salary"])
if dept not in stats:
stats[dept] = {"total_salary": 0, "count": 0}
stats[dept]["total_salary"] += salary
stats[dept]["count"] += 1
for dept, info in stats.items():
total = info["total_salary"]
count = info["count"]
average = total / count
print(f"[{dept}] 社員数: {count} 人, 合計: {total} 円, 平均: {average:.1f} 円")
Pythonここで深掘りしたいポイントは、かなり大事です。
stats は「部署名 → 集計情報(合計と件数)」を持つ辞書になっている。
部署ごとに「初めて出てきたとき」に、{"total_salary": 0, "count": 0} を作っている。
その後は、同じ部署が出てくるたびに「その部署の合計と件数」を更新している。
つまり、
「グループごとの集計=キー付きの辞書にためていく」
というパターンです。
この感覚は、
実務データ処理で本当に頻繁に使います。
CSVをソートして別ファイルに出力する
salary の高い順に並べ替える
次は、「給与の高い順に並べ替えたCSV」を作ってみます。
やることは、
一度全部読み込んでリストにためる
sorted で並べ替える
DictWriter で書き出す
という流れです。
import csv
def sort_employees_by_salary_desc(input_file, output_file):
with open(input_file, "r", encoding="utf-8", newline="") as f_in:
reader = csv.DictReader(f_in)
rows = []
for row in reader:
row["age"] = int(row["age"])
row["salary"] = int(row["salary"])
rows.append(row)
rows_sorted = sorted(rows, key=lambda r: r["salary"], reverse=True)
fieldnames = ["id", "name", "age", "department", "salary"]
with open(output_file, "w", encoding="utf-8", newline="") as f_out:
writer = csv.DictWriter(f_out, fieldnames=fieldnames)
writer.writeheader()
for row in rows_sorted:
row_to_write = {
"id": row["id"],
"name": row["name"],
"age": str(row["age"]),
"department": row["department"],
"salary": str(row["salary"]),
}
writer.writerow(row_to_write)
print(f"{output_file} に給与の高い順で書き出しました。")
Pythonここでの重要ポイントは、少し多めです。
一度 rows に全部ためてから sorted していること。key=lambda r: r["salary"] で「salary を基準に並べ替えている」こと。reverse=True で「降順(大きい順)」にしていること。
書き出すときに、数値を str() で文字列に戻していること。
このパターンを覚えると、
「年齢順」「名前順」「部署順」など、
いろんな並べ替えが書けるようになります。
ソートとフィルタを組み合わせる
「30歳以上を給与の高い順に並べる」
最後に、少しだけ欲張ってみます。
やりたいことは、
30歳以上の社員だけを対象にする
その中で給与の高い順に並べる
結果を別CSVに出す
というものです。
import csv
def filter_and_sort_employees(input_file, output_file):
with open(input_file, "r", encoding="utf-8", newline="") as f_in:
reader = csv.DictReader(f_in)
rows = []
for row in reader:
age = int(row["age"])
salary = int(row["salary"])
if age >= 30:
row["age"] = age
row["salary"] = salary
rows.append(row)
rows_sorted = sorted(rows, key=lambda r: r["salary"], reverse=True)
fieldnames = ["id", "name", "age", "department", "salary"]
with open(output_file, "w", encoding="utf-8", newline="") as f_out:
writer = csv.DictWriter(f_out, fieldnames=fieldnames)
writer.writeheader()
for row in rows_sorted:
row_to_write = {
"id": row["id"],
"name": row["name"],
"age": str(row["age"]),
"department": row["department"],
"salary": str(row["salary"]),
}
writer.writerow(row_to_write)
print(f"{output_file} に 30歳以上を給与の高い順で書き出しました。")
Pythonここでの流れを、日本語だけで整理してみます。
入力CSVを DictReader で読み、1行ずつ辞書として受け取る。
年齢と給与を整数に変換する。
30歳以上なら、その行を rows に追加する。rows を給与の高い順に sorted する。
結果を DictWriter で別CSVに書き出す。
これで、
「条件で絞り込み → 並べ替え → 別CSVに出力」
という、かなり実務的な処理が完成します。
3日目で絶対に押さえておきたいポイント
集計・ソート・レポートの“型”を体に入れる
今日の本質は、これです。
数値列は必ず int や float に変換してから計算する。
合計と平均は「total と count をループでためて、最後に total / count」。
条件付き集計は「if 条件」を挟むだけで実現できる。
グループごとの集計は「キー付きの辞書(部署名 → 合計・件数)」にためていく。
ソートは「一度リストにためてから、sorted(key=…, reverse=…)」で並べ替える。
4日目以降は、
ここに「複数CSVの突き合わせ」「エラー行のスキップ」「ログ出力」などを足していきます。
でも、土台は今日のこれだけです。
「読む → 数値に変換 → 集計・ソート → 書き出す」
この流れが見えたら、
CSVはもう“ただのファイル”ではなく、
あなたが自由に料理できる「実務データ」になっています。

