入出力

【Python】CSVファイルの入出力

【Python】CSVファイルの入出力
naoki-hn

Python での CSV ファイルの入出力方法について解説します。

CSV ファイルの入出力方法

CSV ファイルは、Comma Separated Value の略でカンマ「,」で区切られた値のファイルのことです。拡張子は .csv になります。各種データを保存する際のフォーマットとしてよく使用されるファイル形式でプログラミングでよく使用します。

Python では、CSV ファイルを扱うために csv モジュールが用意されており、簡単にCSV ファイルの入出力が可能です。

この記事では csv モジュールを使用した CSV ファイルの入出力について紹介します。

CSV ファイルを読み込む reader

CSV ファイルを読み込む場合は、csv モジュールの reader 関数を使用します。

基本的な読み込み方法

sample.csv というファイルを使った例で見ていきましょう。もちろん、任意の CSV ファイルを用意して使ってもらっても構いません。

【sample.csvの中身】
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1
import csv

with open("sample.csv", "r", encoding="utf-8") as file:
    reader = csv.reader(file)
    # データを取得する
    data = [row for row in reader]

print(data)
【実行結果】
[['1', '田中太郎', '2021/1/1'], ['2', '伊藤洋子', '2020/9/1'], ['3', '佐藤花子', '2019/1/1']]

csv モジュールを使用するには「import csv」でインポートします。

まずは、open 関数により対象となる CSV ファイルを読み取りモード("r")で開き、オブジェクト(上記例では file)を csv モジュールの reader の引数に渡します。

reader 関数から返却されたオブジェクトを for 文に指定すると、CSV の行単位に値を取得できます。例では、リスト内包表記で data を作成しています。

CSV ファイルを読み込む場合、ファイルを open してから各行を読み込み str.split で分割する方法も考えられますが、csv.reader メソッドを使用する方が簡単です。

リスト内包表記については「リスト(list)内包表記の使い方」を参考にしてください。

区切り文字を指定する場合 delimiter

CSV ファイルは、Comma Separated Values と言われる通りカンマ「,」での区切りが基本ですが、タブ (tab) 等の別の区切り文字が使用される場合もあります。

csv.reader 関数では delimiter 引数で、区切り文字を指定することができます。

カンマ「,」ではなくタブ「\t」で区切られているファイルを扱う場合は以下のようにします。sample_tab.csv の間の空白はタブとなっているファイルを用意してください。

【sample_tab.csv】
1	田中太郎	2021/1/1
2	伊藤洋子	2020/9/1
3	佐藤花子	2019/1/1
import csv

with open("sample_tab.csv", "r", encoding="utf-8") as file:
    # delimiterで区切り文字を指定
    reader = csv.reader(file, delimiter="\t")
    # データを取得する
    data = [row for row in reader]

print(data)
【実行結果】
[['1', '田中太郎', '2021/1/1'], ['2', '伊藤洋子', '2020/9/1'], ['3', '佐藤花子', '2019/1/1']]

上記例では csv.reader 関数の引数として「delimiter="\t"」を指定することで、タブを区切り文字としてデータを読み込んでいます。

CSV ファイルを書き込む writer

CSV ファイルを書き込む場合は、csvモジュールの writer 関数を使用します。

行ごとに書き込む場合 writerow

行ごとに CSV ファイルに書き込むには、writerow メソッドを使用します。

以下の例で見ていきましょう。

import csv

data = [
    [1, "田中太郎", "2021/1/1"],
    [2, "伊藤洋子", "2020/9/1"],
    [3, "佐藤花子", "2019/1/1"],
]

with open("out_writerow.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)

    # writerowで1行ずつ書き込み
    writer.writerow(data[0])
    writer.writerow(data[1])
    writer.writerow(data[2])
【実行結果のout_writerow.csvの中身】
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1

まずは、open 関数により対象の CSV ファイルを書き込みモード("w")で開き、オブジェクト(上記の例では file )を csv モジュールの writer 関数の引数に渡します。

writer 関数から返却されたオブジェクトの writerow メソッドに書き込み対象のリストを渡すことで CSV ファイルとして書き込むことができます。

Windows 環境だと改行は「\r\n」となるため、余計な改行が出力されてしまいます。file 関数で open する際に「newline=""」を指定することで余計な改行は出力されなくなります。

複数行をまとめて書き込む場合 writerows

上記の例では 1 行ずつ writerow メソッドで書き込みましたが writerows メソッドを使用することで複数行をまとめて書き込むことも可能です。

import csv

data = [
    [1, "田中太郎", "2021/1/1"],
    [2, "伊藤洋子", "2020/9/1"],
    [3, "佐藤花子", "2019/1/1"],
]

with open("out_writerows.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)

    # writerowsでまとめて書き込み
    writer.writerows(data)
【実行結果のout_writerows.csvの中身】
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1

CSV ファイルに追記する場合

既存の CSV ファイルに追記をしたい場合には、以下のように CSV ファイルを open する際に、追記モード("a")を指定すると末尾に行を追加できます。

import csv

data = [1, "XXXXX", "YYYY/MM/DD"]

with open("out_writerow_add.csv", "a", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)

    # writerowやwriterowsで追記
    writer.writerow(data)

上記の例では実行するたびに「1, "XXXXX", "YYYY/MM/DD"」という行が追記されていきます。例では writerow で 1 行ずつ追記していますが、もちろん writerows で複数行まとめて追記してもらっても構いません。

辞書形式で CSV ファイルを読み込む DictReader

CSV ファイルには各列の意味を表すヘッダ行があることが多いです。この時、各行の値を辞書の形式で取得できた方が便利な場合があります。

CSV ファイルを辞書形式で取得する場合には、csv モジュールの DictReader を使用することができます。DictReader は関数ではなくクラスです。

基本的な読み込み方法

sample_header.csv というヘッダーを含むファイルを使った例で見ていきましょう。

【sample_header.csv】
id,name,date
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1
import csv

with open("sample_header.csv", "r", encoding="utf-8") as file:
    dict_reader = csv.DictReader(file)
    # データを取得する
    data = [row for row in dict_reader]

# データを表示
print(data, "\n")

# 1行目のデータを表示
print(data[0]["id"])
print(data[0]["name"])
print(data[0]["date"])
【実行結果】
[{'id': '1', 'name': '田中太郎', 'date': '2021/1/1'}, {'id': '2', 'name': '伊藤洋子', 'date': '2020/9/1'}, {'id': '3', 'name': '佐藤花子', 'date': '2019/1/1'}] 

1
田中太郎
2021/1/1

DictReader を使用する場合は、上記のように open で開いたファイルオブジェクトを DictReader の引数に渡してオブジェクトを生成します。

生成したオブジェクトは for 文で繰り返し各行を取得できます。上記例ではリスト内包表記で data というリストを作成しています。

data の各行は辞書データとして取得され、列名: 値 という形の辞書であることが分かります。このようにデータを取得しておくと、例えば 1 行目 (インデックスとしては 0 ) の "id" の値を取得したい場合は「data[0]["id"]」のようにアクセスできます。

ヘッダーがない CSV ファイルを列名指定して読み込む fieldnames

ヘッダー行がない CSV ファイルの場合でも各行の意味が分かっている時には、列名を指定して読み込みたくなります。このような場合には、fieldnames 引数に列名を指定することで、指定した列名としてデータを取得できます。

【sample.csv】
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1
import csv

with open("sample.csv", "r", encoding="utf-8") as file:
    dict_reader = csv.DictReader(file, fieldnames=["id", "name", "date"])
    # データを取得する
    data = [row for row in dict_reader]

# データを表示
print(data, "\n")

# 1行目のデータを表示
print(data[0]["id"])
print(data[0]["name"])
print(data[0]["date"])
【実行結果】
[{'id': '1', 'name': '田中太郎', 'date': '2021/1/1'}, {'id': '2', 'name': '伊藤洋子', 'date': '2020/9/1'}, {'id': '3', 'name': '佐藤花子', 'date': '2019/1/1'}] 

1
田中太郎
2021/1/1

上記例では、元の CSV ファイルにヘッダー行はないですが、fieldnames で指定した列名としてデータ取得できています。

辞書形式のデータを CSV ファイルに書き込む DictWriter

辞書形式のデータを CSV ファイルに書き込みたい場合には、csv モジュールの DictWriter を使用することができます。DictWriterは関数ではなくクラスです。

行ごとに書き込む場合 writerow

DictWriter を使って行ごとに辞書形式のデータを書き込む場合には、以下のように writerow メソッドを使用します。

import csv

data = [
    {"id": 1, "name": "田中太郎", "date": "2021/1/1"},
    {"id": 2, "name": "伊藤洋子", "date": "2020/9/1"},
    {"id": 3, "name": "佐藤花子", "date": "2019/1/1"},
]

with open("out_dict_writerow.csv", "w", newline="", encoding="utf-8") as file:
    # ヘッダーの列名を指定
    field_names = ["id", "name", "date"]
    dict_writer = csv.DictWriter(file, fieldnames=field_names)

    # ヘッダーの書き込み
    dict_writer.writeheader()
    # writerowで1行ずつ書き込み
    dict_writer.writerow(data[0])
    dict_writer.writerow(data[1])
    dict_writer.writerow(data[2])
【実行結果のout_dict_writerow.csvの中身】
id,name,date
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1

DictWriter を使用する場合には、上記のように field_names 引数で列名のリストを渡してオブジェクトを生成する必要があります。

ヘッダー行の書き込みは、writeheader を使用します。その後に各行の書き込みを行う場合は、reader 関数の場合と同じように writerow で書き込みできます。

複数行をまとめて書き込む場合 writerows

上記の例では 1 行ずつ writerow メソッドで書き込みましたが、writerows メソッドを使用することで複数行をまとめて書き込むことも可能です。

import csv

data = [
    {"id": 1, "name": "田中太郎", "date": "2021/1/1"},
    {"id": 2, "name": "伊藤洋子", "date": "2020/9/1"},
    {"id": 3, "name": "佐藤花子", "date": "2019/1/1"},
]

with open("out_dict_writerows.csv", "w", newline="", encoding="utf-8") as file:
    # ヘッダーの列名を指定
    field_names = ["id", "name", "date"]
    dict_writer = csv.DictWriter(file, fieldnames=field_names)

    # ヘッダーの書き込み
    dict_writer.writeheader()
    # writerowsでまとめて書き込み
    dict_writer.writerows(data)
【実行結果のout_dict_writerows.csvの中身】
id,name,date
1,田中太郎,2021/1/1
2,伊藤洋子,2020/9/1
3,佐藤花子,2019/1/1

上記のように各行の辞書データを含むリストになっている場合には writerows を使う方が便利です。

データ分析の際の CSV ファイル入出力

データ分析を行う場合には、NumPy や pandasを使用する場合がほとんどです。データ分析のデータ操作は pandas の DataFrame や Series を使用するのが便利です。

DataFrame で CSV ファイルを入出力する方法については「DataFrameによるCSVファイルの入出力」を参考にしてください。

NumPy と pandas の使い分けはどうするべきかと思うかもしれません。主な違いは以下の通りです。

項目NumPypandas
扱うデータの種類主に数値数値や文字などの様々なデータ種類
演算速度高速NumPy に比べると遅い
得意な処理数値演算や行列演算データ整形、欠損値処理や SQL のようなデータ処理

NumPy は主に数値データを扱い大規模演算を高速に行うのに適しており、pandas はデータ加工に適しています。そのため、データの前処理は pandas で行い、必要に応じて NumPy の配列である ndarray に変換して数値演算をしたり、各種機械学習パッケージと連携したりといった使い方が適した使い方です。

まとめ

Python での CSV ファイルの入出力方法について解説しました。

CSV ファイルは、Comma Separated Valueの略で、カンマ「,」で区切られた値のファイルのことで、各種データ保存のファイルフォーマットとしてよく使用されます。

Python では、csv モジュールの各種関数・メソッドやクラスを使用することで簡単に入出力できますので、是非使い方を覚えてもらえればと思います。

csv モジュールの公式ドキュメントはこちらを参照してください。

ソースコード

上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

あわせて読みたい
【Python Tech】プログラミングガイド
【Python Tech】プログラミングガイド
ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。 私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

プログラミング言語はこれまでC、C++、JAVA等を扱ってきましたが、最近では特に機械学習等の分析でも注目されているPythonについてとても興味をもって取り組んでいます。これまでの経験をもとに、Pythonに興味を持つ方のお役に立てるような情報を発信していきたいと思います。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました