Tag: python Tag: csv

大きなCSVファイルをメモリに大きな負荷をかけずに処理。

大きなCSVファイルを扱う場合、ファイルの中身をすべて一度に読み込もうとするとメモリ(コンピュータの一時的な作業スペース)が溢れてしまい、プログラムがフリーズしたりエラーで停止したりすることがあります。

これを防ぐためには、データを「1行読み込んでは処理し、次の1行を読み込む」という方法をとります。ここで、前回学んだ open() と、前々回学んだ next() が大活躍します。

まずは、ここから出てくる専門用語を整理します。

  • モジュール (Module): 特定の機能(今回はCSVを扱う機能)をまとめた、拡張パーツのようなプログラムのことです。
  • 標準ライブラリ (Standard Library): Pythonをインストールした時点から用意されているモジュール群のことです。追加のインストールなしですぐに使えます。
  • ヘッダー行 (Header Row): CSVファイルの1行目によくある、「名前」「年齢」「メールアドレス」などの列のタイトル(見出し)のことです。

1行ずつ読み込む基本の書き方

Pythonに標準で用意されている csv モジュールと、for 文を組み合わせるのが最も安全で簡単な方法です。

ファイルオブジェクト(またはそれを変換した csv.reader)を for 文で回すと、Pythonは自動的にデータを1行分だけメモリに読み込み、処理が終わると捨てて次の行に進むという賢い動きをしてくれます。

すべて開くすべて閉じる
 
 
-
!
 
-
!
 
-
|
|
!
 
 
-
!
-
!
-
!
 
import csv  # 準備: csvモジュールを使えるようにする
 
# 1. with構文でファイルを開く
with open("large_data.csv", mode="r", encoding="utf-8") as f:
    
    # 2. 読み込んだファイルを csv.reader に渡す
    reader = csv.reader(f)
    
    # 3. next() の出番!
    # 1回だけ next() を呼ぶことで、1行目(ヘッダー行)だけを先に取り出す
    # これにより、以降の for 文では「2行目のデータ」から処理が始まります
    header = next(reader)
    print(f"見出し: {header}")
    
    # 4. for文で残りのデータを1行ずつ処理する
    for row in reader:
        # row には ["田中", "25", "東京"] のように、1行分のデータがリストとして入る
        
        # 必要な処理だけを行う(例: 2番目の項目が "25" の人だけ表示する)
        if row[1] == "25":
            print(f"25歳の人を見つけました: {row[0]}")




フィールドの情報でグループにして扱う

想定しているデータ

日付,現在の氏名,在校時の氏名,3年時クラス
7/10/26 11:19,山田太郎,,3組
7/10/26 11:20,長岡 花子,,5組
7/10/26 11:20,夏木 義男,,5組
7/10/26 11:21,日本夏子,,3組
7/10/26 11:22,井上博,,10組

3年時クラスでまとめて、HTMLのTABLEタグにして出力します。

すべて開くすべて閉じる
 
 
 
-
!
 
-
!
 
 
 
-
|
!
 
 
-
!
-
!
-
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
!
 
 
 
 
-
!
 
 
-
!
 
-
!
 
 
 
 
 
 
 
-
!
import csv
from collections import defaultdict
 
# データをクラスごとにまとめるためのディクショナリ(辞書)を作成
class_data = defaultdict(list)
 
# テキストファイルを読み込む
file_path = 'test.csv'
try:
    with open(file_path, mode='r', encoding='utf-8') as file:
        reader = csv.reader(file)
        # --- ここが追加・修正ポイント ---
        # 1行目(項目名などのヘッダー)を読み飛ばす
        try:
            next(reader)
        except StopIteration:
            # ファイルが空だった場合は何もしない
            pass 
        # -------------------------------
        
        # 2行目以降からループ処理が始まる
        for row in reader:
            if len(row) >= 3:
                name = row[1].strip()
                oldName =  row[2].strip()
                if oldName != '':
                    name = oldName
                name = name.replace(" ", "")
                name = name.replace(" ", "")
                grade = '3'
                class_name = row[3].strip()
                class_name = class_name.replace("1", " 1")
                class_name = class_name.replace("2", " 2")
                class_name = class_name.replace("3", " 3")
                class_name = class_name.replace("4", " 4")
                class_name = class_name.replace("5", " 5")
                class_name = class_name.replace("6", " 6")
                class_name = class_name.replace("7", " 7")
                class_name = class_name.replace("8", " 8")
                class_name = class_name.replace("9", " 9")
                
                # 学年が「3」の場合のみ処理
                if grade == '3':
                    class_data[class_name].append(name)
except FileNotFoundError:
    print("ファイルが見つかりません。")
 
# HTMLのTABLEタグを生成
html_output = "<table border=\"1\">\n"
html_output += "  <tr><th>クラス</th><th>人数</th><th>生徒名</th></tr>\n"
 
# クラス名でアルファベット順にソートして出力
gokei_num = 0
for class_name in sorted(class_data.keys()):
    # 生徒のリストをカンマ区切りの文字列にする
    students_str = ", ".join(class_data[class_name])
    students_num = len(class_data[class_name])
    gokei_num += students_num
    html_output += f"  <tr><td>3年{class_name}組</td><td>{students_num}名</td><td>{students_str}</td></tr>\n"
 
html_output += "</table>"
html_output += f" {gokei_num} 名"
 
# 結果を出力(実際にはファイルに書き出すことも可能です)
print(html_output)