入出力

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

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

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」でcsvモジュールをインポートします。

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

reader関数から返却されたオブジェクトをfor文に指定すると、csvの行単位に値を取得することができます。上記の例ではリスト内包表記を使ってdataというリストを作成しています。data=[]で空のリストを作成しておいて、普通にfor文で行を取得しつつdata.append(row)のようにしても構いません。

リスト内包表記についてよく分からない方は「リスト(list)内包表記の使い方」でまとめていますので興味があれば参考にしてください。

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

区切り文字を指定する場合(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

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

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ファイルの入出力」でまとめていますので興味があれば参考にしてください。

Note

NumPyとpandasの使い分けについてはどうなのかと勉強を始めると思うかもしれません(私はそうでした)。色々と意見はあるのかもしれませんが、私はNumPyとpandasの違いは以下で理解しています。

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

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

まとめ

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

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

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

Note

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