1. ホーム
  2. 記事一覧
  3. 【徹底解説】PythonでのCSVの扱いについて

2022.11.21

【徹底解説】PythonでのCSVの扱いについて

この記事ではPythonでのCSVファイルの操作について解説します。

Pythonのcsvモジュールは、アプリケーションから取り出したcsvファイルを使って独自の集計やデータの移行などさまざまな場所で活用することができます。

csv モジュールとは?

csvはPythonでCSVファイルを扱えるモジュールのことです。使用するためにはimportする必要があります。

CSVファイルとは、「Comma Separated Values」の略称を指します。名前の通り、値や項目を,(カンマ)で区切って書かれたファイル・データのことを言います。ファイルの拡張子は.csvで、互換性が高い特徴があり、様々なソフトに取り込み・使用ができます。

以下がCSVファイル形式で書いたファイルです。

学校名, 学年, 名前, 専攻カリキュラム, 成績
Envader, 1st, Bob, Programming, A
Envader, 2nd, Alisa, UI/UX, B
Envader, 1st, Mike, Programming, B
Envader, 2nd, Adam, DataScience, S
Envader, 2nd, Lisa, Front-end, A

上記のファイルの拡張子を.csvにし、ファイルを読み込むと以下のようになります。

ファイル操作

Pythonにおけるcsvファイルの取り扱いを説明します。

  • with

    本記事はwithを使用し、ファイル操作を行います。withはファイルを一定期間操作する構文で、ファイルを自動でクローズするという特徴があります。

    with構文は、open()と組み合わせて以下のように記述します。

    with open(<ファイル名>, mode=<"モード">, encoding="文字コード") as <別名>:
  • open()

    open()の引数のファイル指定は必須です。モードと文字コードは必要に応じて使用・使い分けします。また、 as でファイル操作を行うファイルオブジェクトに別名を付けることができ、その別名はファイルをクローズするまでのスコープで使用できます。

    モードはいくつかの種類とそれぞれの特徴がありますので表にまとめました。

    mode詳細特徴
    r読み込み用デフォルト値
    w書き込み用
    x新規作成 + 書き込み用既にファイルがあるとエラーになる
    a追記用
    bバイナリモードr, w, aと一緒に指定が必要
    tテキストモードr, w, aと一緒に指定が必要
    +更新用r, w, a, xと一緒に指定が必要

csvモジュールの主な関数

今回紹介するcsvモジュールの関数を表にまとめました。

関数詳細特徴
csv.readerファイルの読み込みリスト型を返す
csv.Dictreaderファイルの読み込み辞書型を返す
csv.writerファイルの書き込みリスト型を書き込む
csv.DictWriterファイルの書き込み辞書型を書き込む

CSVモジュールを使った読み込み

ここから、実際にcsvモジュールを使ってCSVファイルを操作していきます。まずはCSVファイルの読み込み操作から行います。

csv.reader

csv.readerは、CSVファイルの各行をリストとして読み込みます。

  • 基本的な使い方

    以下のCSVファイル(sample.csv)を読み込みます。

    学校名,学年,名前,専攻カリキュラム,成績
    Envader,1st,Bob,Programming,A
    Envader,2nd,Alisa,UI/UX,B
    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
        # ①
        print(reader_object)
    
        # ②
        for row in reader_object:
            print(row)
    
    # 出力結果①: <_csv.reader object at 0x1029fc040>
    
    # 出力結果②:
    # ['学校名', '学年', '名前', '専攻カリキュラム', '成績']
    # ['Envader', '1st', 'Bob', 'Programming', 'A']
    # ['Envader', '2nd', 'Alisa', 'UI/UX', 'B']

    出力結果①は、open()で開いたファイルオブジェクトをcsv.reader()に渡して出力した結果です。csv.readerでファイルオブジェクトを読み込むとreaderオブジェクトが返されます。

    csv.readerが返したreaderオブジェクトはイテレータプロトコルに対応します。そのため、②のようにfor文で行ごとに取り出すことができます。

  • 二次元配列として取得

    以下のCSVファイル(sample.csv)を読み込み、二次元リストで出力します。

    1,2,3,4
    5,6,7,8
    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        # リスト内包表記を使用して二次元リストを取得
        sample_list = [row for row in reader_object]
    
    print(sample_list)
    # 出力結果:
    # [['1', '2', '3', '4'], ['5', '6', '7', '8']]

行・要素・列の取得

以下のCSVファイル(sample.csv)の、「行・要素・列」を取得します。

1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
17,18,19,20
  • 行の取得

    行の取得は、二次元リストに対してインデックス指定、またはスライスを行います。

    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        sample_list = [row for row in reader_object]
    
    # ①index指定
    print(sample_list[0])
    print(sample_list[-1])
    # 出力結果:
    # ['1', '2', '3', '4']
    # ['9', '10', '11', '12']
    
    # ②スライス
    print(sample_list[3:])
    print(sample_list[0:2])
    # 出力結果:
    # [['13', '14', '15', '16'], ['17', '18', '19', '20']]
    # [['1', '2', '3', '4'], ['5', '6', '7', '8']]
  • 要素の取得

    要素の取得は、二次元リストに対してインデックス指定を行います。インデックス指定は①のように、「リスト内の何番目のリスト + 何番目の要素」を指定します。

    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        sample_list = [row for row in reader_object]
    
    print(sample_list[0][0])
    print(sample_list[2][3])
    # 出力結果:
    # 1
    # 12
  • 列の取得

    列の取得方法は二種類あります。一つ目は、二次元リストの行と列を入れ替える(転置)方法です。

    import csv
    import pprint # コード整形用
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        sample_list = [row for row in reader_object]
    
        # ①行と列を入れ替える(転置)
        columns_list = [list(x) for x in zip(*sample_list)]
        pprint.pprint(columns_list)
        # 出力結果: 
        # [['1', '5', '9', '13', '17'],
        #  ['2', '6', '10', '14', '18'],
        #  ['3', '7', '11', '15', '19'],
        #  ['4', '8', '12', '16', '20']]
    
        # ②特定の列を取得
        print(columns_list[0])
        print(columns_list[3])
        # 出力結果:
        # ['1', '5', '9', '13', '17']
        # ['4', '8', '12', '16', '20']

    2つ目は、readerオブジェクトから行を取り出し、その行の特定のインデックスを繰り返し取得することで列として取得する方法です。

    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        # ①特定の列を取得する
        sample_list1 = [row[0] for row in reader_object]
        print(sample_list1)
        # 出力結果: ['1', '5', '9', '13', '17']
    
    # ②違う列を取得するためにはもう一度ファイル操作から行う必要がある
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
        sample_list2 = [row[3] for row in reader_object]
        print(sample_list2)
        # 出力結果: ['4', '8', '12', '16', '20']

    上記の①と②を見ての通り、最初に取得した列とは違う列を取得するためには、再度CSVファイルをオープンする所から始める必要があります。

    csvモジュールを用いて列を取得する方法はどちらも多少の手間がかかります。ここでは紹介しませんが、ライブラリのNumpyやpandasを使用すると、もっと簡単に多次元の操作をすることが可能です。

文字列を数値に変換

CSVファイルから取り出した値はデフォルトで文字列型です。そのため、CSVファイルからデータを取得し、そのデータを更に加工するためには数値に変換する必要があります。

今回は取り出した文字列型をint型とfloat型に変換する方法を紹介します。

  • int型に変換

    以下のCSVファイル(sample.csv)を使用し、int型に変換します。

    1, 2, 3, 4
    5, 6, 7, 8
    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        # ①二次元リストを取得
        sample_list = [row for row in reader_object]
    
    # ②取り出した要素の型を確認する
    print(sample_list[0][0])
    print(type(sample_list[0][0]))
    # 出力結果:
    # 1
    # <class 'str'>
    
    # ③二次元リストの最初の行をint型に変換する
    int_list = [int(i) for i in sample_list[0]]
    print(int_list)
    print(type(int_list[0]))
    # 出力結果:
    # [1, 2, 3, 4]
    # <class 'int'>
    
    # ④二次元リストを一気にint型に変換する
    print([[int(i) for i in row] for row in sample_list])
    # 出力結果:
    # [[1, 2, 3, 4], [5, 6, 7, 8]]
  • float型に変換

    float型への変換は二種類のやり方があります。まずはint型に変換した時と同様に行います。

    以下のCSVファイル(sample.csv)を使用します。

    1.2,1.2,1.3,1.4
    1.5,1.6,1.7,1.8
    import csv
    
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
    
        sample_list = [row for row in reader_object]
    
    # ①CSVファイルの最初の行をfloat型に変換する
    float_list = [float(i) for i in sample_list[0]]
    print(float_list)
    print(type(float_list[0]))
    # 出力結果:
    # [1.2, 1.2, 1.3, 1.4]
    # <class 'float'>
    
    # ②二次元リストを一気にfloat型に変換する
    print([[float(i) for i in row] for row in sample_list])
    # 出力結果:
    # [[1.2, 1.2, 1.3, 1.4], [1.5, 1.6, 1.7, 1.8]]

    もう一つのやり方は、ファイルオブジェクトから読む込む時点でfloat型へ変換します。

    import csv
    
    with open("sample.csv") as file_object:
        # ①csv.readerの引数にquoting=csv.QUOTE_NONNUMERICを追加
        reader_object = csv.reader(file_object, quoting=csv.QUOTE_NONNUMERIC)
    
        sample_list = [row for row in reader_object]
    
    # ②要素の型を確認する
    print(sample_list[0][0])
    print(type(sample_list[0][0]))
    # 出力結果:
    # 1.1
    # <class 'float'>

    ①のように、QUOTE_NONNUMERICを指定するとファイルオブジェクトから読み込む時点で、全てのフィールドをfloat型に変換することができます。こちらのやり方の方が簡単にfloat型に変換することができます。

区切り文字の指定

csv.reader()のデフォルトの区切り文字は,(カンマ)です。デフォルト以外を指定するためには、csv.reader()の引数のdelimiterに任意の区切り文字を指定します。

以下の空白で区切られたCSVファイル(sample.csv)を使用し、区切り文字を空白に指定して読み込みます。

1 2 3 4
5 6 7 8
import csv

with open("sample.csv") as file_object:
    # ①区切り文字を空白に指定
    reader_object = csv.reader(file_object, delimiter=" ")

    sample_list = [row for row in reader_object]

print(sample_list)
# 出力結果: [['1', '2', '3', '4'], ['5', '6', '7', '8']]

引用符の扱い

CSVファイルには引用符が入っている時があります。その場合、csv.readerが引用符をどう処理するのかを見てみます。

引用符の(ダブルクオーテーション)が使われている以下のCSVファイル(sample.csv)を使用します。

商品 単価 数量
A商品 500 1
B商品 900 3
"Python csvの本" 1500 1
import csv

with open("sample.csv", encoding="UTF-8") as file_object:
    reader_object = csv.reader(file_object, delimiter=" ")

    for row in reader_object:
        print(row)

# 出力結果: 
# ['商品', '単価', '数量']
# ['A商品', '500', '1']
# ['B商品', '900', '3']
# ①['Python csvの本', '1500', '1']

出力結果①を見て頂きたいのですが、CSVファイルにあったが出力されていません。このように、csv.readerはデフォルトで引用符を無視します。基本的にはこの動作で問題ないですが、この引用符に対しての処理を行って欲しくない場合は以下のように行います。

import csv

with open("sample.csv", encoding="UTF-8") as file_object:
    # ①csv.readerの引数にquoting=csv.QUOTE_NONEを指定
    reader_object = csv.reader(file_object, delimiter=" ", quoting=csv.QUOTE_NONE)

    for row in reader_object:
        print(row)

# 出力結果:
# ['商品', '単価', '数量']
# ['A商品', '500', '1']
# ['B商品', '900', '3']
# ②['"Python', 'csvの本"', '1500', '1']

改行を含むファイルの扱い

改行を含んだCSVファイルを読み込む場合、open()の引数にnewline=’’を指定することが推奨されています。これはOSによる改行コードの扱いの違いを同じように処理できるためです。改行に関するPythonの公式ドキュメントの説明を以下に引用します。

newline=''が指定されない場合、クォートされたフィールド内の改行は適切に解釈されず、書き込み時に \r\nを行末に用いる処理系では余分な \rが追加されてしまいます。csv モジュールは独自(universal) の改行処理を行うため、newline=''を指定することは常に安全です。(参照:csv --- CSV ファイルの読み書き

headerを含むファイルの扱い

header(見出し行・見出し列)を含んだCSVファイルの「数値データだけ」を使いたいという場合は多いと思います。以下のようなheaderを含んだCSVファイル(sample.csv)から、header以外のデータだけを抽出する方法を紹介します。

,Bob,Lisa,Mike,Alisa
Math,70,30,80,60
English,90,85,50,70
Science,80,100,50,80
Japanese,80,70,90,85
import csv
import pprint # データ整形のために使用

with open("sample.csv") as file_object:
    reader_object = csv.reader(file_object)

    # ①headerを含む全てのCSVファイルを取得
    sample_list = [row for row in reader_object]

pprint.pprint(sample_list)
# 出力結果:
# [['', 'Bob', 'Lisa', 'Mike', 'Alisa'],
#  ['Math', '70', '30', '80', '60'],
#  ['English', '90', '85', '50', '70'],
#  ['Science', '80', '100', '50', '80'],
#  ['Japanese', '80', '70', '90', '85']]

# ② ①から数値データ部分のみを取得する
pprint.pprint([row [1:] for row in sample_list[1:]])
# 出力結果:
# [['70', '30', '80', '60'],
#  ['90', '85', '50', '70'],
#  ['80', '100', '50', '80'],
#  ['80', '70', '90', '85']]

# ③ ①から数値データ部分を抽出する時点でint型に変換する
print([[int(i) for i in row[1:]] for row in sample_list[1:]])
# 出力結果:
# [[70, 30, 80, 60], [90, 85, 50, 70], [80, 100, 50, 80], [80, 70, 90, 85]]

header以外を抽出したい、などの細かい条件に合わせたファイル操作はpandasを使用するともっと簡単に行うことができます。

csv. DictReader

Pythonのcsvモジュールに用意されたファイルの読み込みには、csv.reader以外にcsv.DictReaderがあります。csv.readerはCSVファイルをリストとして読み込みますが、csv.DictReaderはCSVファイルを辞書として読み込みます。

  • 基本的な使い方

    以下のCSVファイル(sample.csv)を使用します。

    A,B,C,D
    1,2,3,4
    5,6,7,8
    import csv
    import pprint
    
    with open("sample.csv") as file_object:
        # ①
        dict_reader_object = csv.DictReader(file_object)
    		# ②
        sample_dict = [row for row in dict_reader_object]
    
    # ③dict型を返す
    pprint.pprint(sample_dict)
    # 出力結果:
    # [{'A': '1', 'B': '2', 'C': '3', 'D': '4'},
    #  {'A': '5', 'B': '6', 'C': '7', 'D': '8'}]

    ①、②のように、基本的な使い方はcsv.readerと同じです。また、行・要素・列もcsv.readerで紹介した方法で取得できます。

    ③の出力結果のように、CSVファイルのフィールド(列)の最初の値がキーとなり、二番目以降の値がキーに対応する形で出力されます。

    また、csv.DictReaderの返す型はPythonバージョン3.8からdict型を返すようになりました。(参照: csv --- CSV ファイルの読み書き csv.DictReader

header(見出し行)がない場合

csv.DictReaderの特徴は見出し行が辞書型のキーとなる点です。もし、CSVファイルに見出し行がない場合、どう出力されるかを以下のCSVファイル(sample.csv)を使用して見てみます。

1,2,3,4
5,6,7,8
9,10,11,12
import csv
import pprint

with open("sample.csv") as file_object:
    dict_reader_object = csv.DictReader(file_object)

    sample_dict = [row for row in dict_reader_object]

# ①
pprint.pprint(sample_dict)
# 出力結果:
# [{'1': '5', '2': '6', '3': '7', '4': '8'},
#  {'1': '9', '2': '10', '3': '11', '4': '12'}]

csv.DictReaderは、デフォルトでは「CSVファイルのフィールドの最初の値」をキーとします。もし見出し行がないCSVファイルを読み込んだ場合、①の出力結果のように関連のないキーと値のセットになってしまいます。

csv.DictReaderの引数にfieldnamesを指定すると、任意の値を見出し行として設定し、その値を辞書のキーとして設定することができます。

import csv
import pprint

with open("sample.csv") as file_object:
    # ②見出し行にA,B,C,Dを指定する
    dict_reader_object = csv.DictReader(file_object, fieldnames=["A", "B", "C", "D"])

    sample_dict = [row for row in dict_reader_object]

# ③
pprint.pprint(sample_dict)
# 出力結果:
# [{'A': '1', 'B': '2', 'C': '3', 'D': '4'},
#  {'A': '5', 'B': '6', 'C': '7', 'D': '8'},
#  {'A': '9', 'B': '10', 'C': '11', 'D': '12'}]

header(見出し列)の削除方法

今度は見出し列があるCSVファイルを読み込んだ場合を、以下のCSVファイル(sample.csv)を使用して見てみます。

A,B,C,D
Bob,80,70,90,100
Lisa,90,100,70,80
Alisa,70,80,100,100
import csv
import pprint

with open("sample.csv") as file_object:
    dict_reader_object = csv.DictReader(file_object)

    sample_dict = [row for row in dict_reader_object]

# ①見出し列を含めた出力結果
pprint.pprint(sample_dict)
# 出力結果:
# [{'': 'Bob', 'A': '80', 'B': '70', 'C': '90', 'D': '100'},
#  {'': 'Lisa', 'A': '90', 'B': '100', 'C': '70', 'D': '80'},
#  {'': 'Alisa', 'A': '70', 'B': '80', 'C': '100', 'D': '100'}]

①の出力結果のように、csv.DictReaderは、見出し列に対しては特別な処理を行いません。見出し列を除外したい場合はpop()popitem()delなどを使用します。今回はpop()を使用し、見出し列を削除します。

import csv
import pprint

with open("sample.csv") as file_object:
    dict_reader_object = csv.DictReader(file_object)

    sample_dict = [row for row in dict_reader_object]

# ②見出し列の削除
print([hc.pop("") for hc in sample_dict])
# 出力結果: ['Bob', 'Lisa', 'Alisa']

# ③見出し列の削除後の辞書を出力する
pprint.pprint(sample_dict)
# 出力結果:
# [{'A': '80', 'B': '70', 'C': '90', 'D': '100'},
#  {'A': '90', 'B': '100', 'C': '70', 'D': '80'},
#  {'A': '70', 'B': '80', 'C': '100', 'D': '100'}]

csvモジュールを使った書き込み

ここからはcsvモジュールを使ったCSVファイルの書き込み操作を行なっていきます。

csv.writer

csv.writerはCSVファイルにリストとして書き込みます。

  • 基本的な使い方

    CSVファイルを新規作成して、そこに書き込みます。新規作成の場合、open()のモードにwを指定します。

    import csv
    
    # ①ここから書き込み
    with open("sample.csv", "w") as file_object:
        writer_object = csv.writer(file_object)
        writer_object.writerow([1, 2, 3])
        writer_object.writerow(["A", "B", "C"])
    
    # ②書き込まれた内容の確認
    with open("sample.csv") as file_object:
        print(file_object.read())
        
    # ③出力結果:
    # 1,2,3
    # A,B,C

    ①の書き込み処理を説明します。

    新規作成モードでCSVファイルを開き、そのファイルオブジェクトをcsv.writerに渡すとwriterオブジェクトが取得できます。このwriterオブジェクトに対して、csv.writerに用意されているwriterow()を使用すると、引数に渡した内容を一行ずつ書き込むことができます。

  • 既存ファイルに追記する場合

    追記する場合はopen()のモードにaに指定します。先ほど新規作成したCSVファイル(sample.csv)に追記します。

    import csv
    
    # ①追記モードで書き込み
    with open("sample.csv", "a") as file_object:
        writer_object = csv.writer(file_object)
        writer_object.writerow([4, 5, 6])
        writer_object.writerow(["D", "E", "F"])
    
    # ②書き込まれた内容の確認
    with open("sample.csv") as file_object:
        print(file_object.read())
    
    # ③出力結果: 末尾に追加される
    # 1,2,3
    # A,B,C
    # 4,5,6
    # D,E,F
  • 二次元リストの書き込み

    csv.writerwriterows()を使用すると、二次元リスト(複数行)を一度に書き込むことができます。

    import csv
    
    # ①書き込む二次元リストを用意
    write_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
    
    # ②ここから書き込み
    with open("sample.csv", "w") as file_object:
        writer_object = csv.writer(file_object)
        writer_object.writerows(write_list)
    
    # ③書き込まれた内容の確認
    with open("sample.csv") as file_object:
        print(file_object.read())
    
    # ④出力結果:
    # 1,2,3,4
    # 5,6,7,8
    # 9,10,11,12

区切り文字の指定

csv.writerの区切り文字のデフォルトは、,(カンマ)区切りで書き込まれます。カンマ以外で書き込みたい場合はcsv.writerの引数にdelimiterと任意の区切り文字を指定します。

import csv
import pprint

# ①書き込む二次元リストを用意
write_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

# ②ここから書き込み
with open("sample.csv", "w") as file_object:
    # ③空白区切りを指定
    writer_object = csv.writer(file_object, delimiter=" ")
    writer_object.writerows(write_list)

# ④ここから読み込み(書き込まれたことの確認)
with open("sample.csv") as file_object:
    reader_object = csv.reader(file_object)

    sample_list = [row for row in reader_object]

pprint.pprint(sample_list, width=40)
# ⑤出力結果:
# [['1 2 3 4'],
#  ['5 6 7 8'],
#  ['9 10 11 12']]

引用符の扱い

csv.writerで引用符を含んだデータを書き込んだ場合、どのようにCSVファイルに書き込まれるかを見てましょう。

import csv

# ①書き込む二次元リストを用意
write_list = [[1, 2, 3], ["A", "B", "CD"], ["E,F,G", "H", "I"]]

# ②ここから書き込み
with open("sample.csv", "w") as file_object:
    writer_object = csv.writer(file_object)
    writer_object.writerows(write_list)

# ③ここから読み込み(書き込まれたことの確認)
with open("sample.csv") as file_object:
    print(file_object.read())

# ④出力結果:
# 1,2,3
# A,B,CD
# "E,F,G",H,I

④の出力結果のように、デフォルトでは「区切り文字のような特別な文字を含む要素のみ」(”E,F,G”だけ)が(ダブルクオーテーション)で囲まれています。

csv.writerの引用符は、引数quotingで制御できます。quotingの指定はいくつか種類があるので表にまとめました。

quoting=引用符の扱い特徴
csv.QUOTE_MINIMAL特別な文字を含む要素のみを引用符で囲むデフォルト
csv.QUOTE_ALL全ての要素を引用符で囲む
quoting.QUOTE_NONNUMERIC数値でない要素が引用符で囲まれる
csv.QUOTE_NONEどの要素も引用符で囲まれないescapecharの文字指定が必要

また、書き込み時の引用符をデフォルトの(ダブルクオーテーション)から変更したい場合は、引数quotecharを指定します。

改行を加えて書き込む場合

csv.writerを使用して任意の場所に改行を入れたい時の方法と、それがCSVファイルにどう書き込まれるかを見てみましょう。

import csv

# ①書き込む二次元リストを用意(改行コードを含む)
write_list = [[1, 2, 3], ["A\n", "B", "C"], [4, "\n5", "6"]]

# ②ここから書き込み
with open("sample.csv", "w", newline='') as file_object:
    writer_object = csv.writer(file_object)
    writer_object.writerows(write_list)

# ③ここから読み込み(書き込まれたことの確認)
with open("sample.csv") as file_object:
    print(file_object.read())

# ④出力結果:
# 1,2,3
# "A
# ",B,C
# 4,"
# 5",6

指定の箇所で改行処理をして書き込みを行いたい場合、①のように要素の前後に改行コードを記述し、要素と改行コードごと引用符で囲みます。

読み込みの際に紹介した理由と同様に、改行を扱う際は②のようにopen()の引数newline’’としておいた方が安全です。

出力結果は④のように、改行コードを含んだ要素は引用符で囲まれてCSVファイルに書き込まれます。

headerなどを加える場合

csv.writerにはheader(見出し行・見出し列の両方)を加えて出力する特別な機能が備わっていません。そのため、見出し行・見出し列を加えたい場合は、そのための処理を自分で行う必要があります。

  • 見出し行を加える場合

    新規作成で見出し行を加えたい場合は、一行目に見出し行を書き込むだけなので簡単です。逆に、既存のファイルに見出し行を加える場合は少し手間がかかります。(追記モードが末尾に文字を挿入するため)

    今回は、以下のCSVファイル(sample.csv)を使って既存のファイルに追記する方法を紹介します。

    import csv
    import pprint
    
    # ①見出し行を用意しておく
    write_header = ["A", "B", "C", "D", "E"]
    
    # ②まずは既存のファイルを読み込んで2次元リストに格納する
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
        sample_list = [row for row in reader_object]
    
    # ③2次元リストの確認
    pprint.pprint(sample_list)
    # [['1', '2', '3', '4', '5'],
    #  ['6', '7', '8', '9', '10'],
    #  ['11', '12', '13', '14', '15']]
    
    # ④既存のファイルを上書きする形(新規作成)で開く
    with open("sample.csv", "w") as file_object:
        writer_object = csv.writer(file_object)
        # ⑤見出し行->既存のファイルデータの順で書き込む
        writer_object.writerow(write_header)
        writer_object.writerows(sample_list)
    
    with open("sample.csv") as file_object:
        print(file_object.read())
    
    # ⑥出力結果: 最終的なsample.csvの中を確認
    # A,B,C,D,E
    # 1,2,3,4,5
    # 6,7,8,9,10
    # 11,12,13,14,15
  • 見出し列を加える場合

    見出し列を加える場合は、各行の先頭に要素を追加する処理が必要です。

    以下のCSVファイル(sample.csv)に見出し列を追加します。

    '',Bob,Lisa,Mike,Alisa
    70,30,80,60
    90,85,50,70
    80,100,50,80
    80,70,90,85
    import csv
    import pprint
    
    # ①見出し列を用意する
    write_index = ["Math","Japanese","Science","English"]
    
    # ②既存のファイルを読み込んで2次元リストに格納する
    with open("sample.csv") as file_object:
        reader_object = csv.reader(file_object)
        sample_list = [row for row in reader_object]
    
    # ③2次元リストの確認
    pprint.pprint(sample_list)
    # [["''", 'Bob', 'Lisa', 'Mike', 'Alisa'],
    #  ['70', '30', '80', '60'],
    #  ['90', '85', '50', '70'],
    #  ['80', '100', '50', '80'],
    #  ['80', '70', '90', '85']]
    
    # ④既存のファイルを上書きする形で、新規作成で開く
    with open("sample.csv", "w") as file_object:
        writer_object = csv.writer(file_object)
        # ⑤見出し行を書き込む
        writer_object.writerow(sample_list[0])
        # ⑥見出し列を先頭に加えながら、残りの2次元リストを書き込む
        for i, row in zip(write_index, sample_list[1:]):
            writer_object.writerow([i] + row)
    
    with open("sample.csv") as file_object:
        print(file_object.read())
    
    # ⑦出力結果: 最終的なsample.csvの中を確認
    # '',Bob,Lisa,Mike,Alisa
    # Math,70,30,80,60
    # Japanese,90,85,50,70
    # Science,80,100,50,80
    # English,80,70,90,85

csv.writerを使用して見出し行・見出し列を追加するためには多少の手間を要します。こういった処理の場合は、pandasを使用するともっと簡単に行うことができます。

csv. DictWriter

Pythonのcsvモジュールに用意されたファイルの書き込みには、csv.writer以外にcsv.DictWriterがあります。csv.writerはCSVファイルをリストとして書き込みますが、csv.DictWriterはCSVファイルを辞書として書き込みます。

  • 基本的な使い方

    import csv
    
    with open("sample.csv", "w") as file_object:
        # ①csv.DictWriterの第2引数にリストを指定する
        dw_object = csv.DictWriter(file_object, ["A", "B", "C"])
    
        # ②writeheader()を実行すると①で指定したリストの要素がヘッダーとして書き込まれる
        dw_object.writeheader()
    
        # ③writerow()で一行ずつ書き込む
        dw_object.writerow({"A": 1, "B": 2, "C": 3})
    
        # ④キーがCの要素を記述しない
        dw_object.writerow({"A": 4, "B": 5})
    
        # ⑤エラーになるパターン
        dw_object.writerow({"D": 4, "B": 5, "C": 6})
        dw_object.writerow({"": 4, "B": 5, "C": 6})
    
    # ⑥ここから読み込み(書き込まれたことの確認)
    with open("sample.csv") as file_object:
        print(file_object.read())
    # ⑦: ①〜④までの出力結果
    # A,B,C
    # 1,2,3
    # 4,5,

    ①では、csv.DictWriterの第一引数に「開いたファイルのオブジェクト」、第二引数に「辞書のキーのリスト」を指定します。こうするとDictWriterオブジェクトが取得できます。

    書き込む際は④のようにキーが存在しない辞書を書き込むことはできますが、⑤のようにヘッダーで設定したキーと違う値を指定したり、キーを省略するとエラーになります。

  • 複数の辞書を一度に書き込む

    import csv
    
    dict1 = {"A": 1, "B": 2, "C": 3}
    dict2 = {"A": 4, "B": 5, "C": 6}
    dict3 = {"A": 7, "C": 9}
    
    with open("sample.csv", "w") as file_object:
        dw_object = csv.DictWriter(file_object, ["A", "B", "C"])
        dw_object.writeheader()
    
        # ①
        dw_object.writerows([dict1, dict2, dict3])
    
    # ②ここから読み込み(書き込まれたことの確認)
    with open("sample.csv") as file_object:
        print(file_object.read())
    # ③出力結果:
    # A,B,C
    # 1,2,3
    # 4,5,6
    # 7,,9

    ①のように、writerows()の引数には複数の辞書を指定することができます。辞書を指定する際にはリストで渡す必要があります。

辞書の特定のキーを書き込みたくない場合

例えば、書き込みたい辞書にはA, B, Cのキーが存在するが、A, Cだけ書き込みたいといった場合です。書き込みたい辞書の特定のキーだけは除外して書き込む方法を紹介します。

import csv

dict1 = {"A": 1, "B": 2, "C": 3}
dict2 = {"A": 4, "B": 5, "C": 6}
dict3 = {"A": 7, "B": 8, "C": 9}

with open("sample.csv", "w") as file_object:
    # ①第二引数には書き込みたいキー
    # ②引数extrasactionをignoreに指定
    dw_object = csv.DictWriter(file_object, ["A", "C"], extrasaction="raise")

    # ③エラーになるパターン
    # dw_object = csv.DictWriter(file_object, ["A", "C"])

    dw_object.writeheader()
    dw_object.writerows([dict1, dict2, dict3])

# ④ここから読み込み(書き込まれたことの確認)
with open("sample.csv") as file_object:
    print(file_object.read())
# ⑤出力結果:
# A,C
# 1,3
# 4,6
# 7,9

②のように、csv.DictWriterに引数extrasaction="ignore"を指定すると、ヘッダーで指定されていないキーを無視することができます。

デフォルトでは引数extrasactionraiseが指定されているため、③のように記述するとValueErrorになります。

まとめ

Pythonのcsvモジュールを使用したCSVファイルの読み書きを解説しました。

csvモジュールは、基本的なCSVファイルの読み書きは比較的簡単に行えます。しかし、複雑な配列処理をしてから読み書きを行おうとすると、手間を要する場合があります。そういった場合は、ライブラリのNumpy、pandasの使用を検討しましょう。

【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

IT未経験者必見 USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。

「フリーランスエンジニア」

近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。

「成功する人とそうでない人の違いは何か?」

私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。

比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。

多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、

note記事3000いいね超えの殿堂記事 今すぐ読む

エンベーダー編集部

エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

RareTECH 無料体験授業開催中! オンラインにて実施中! Top10%のエンジニアになる秘訣を伝授します! RareTECH講師への質疑応答可

関連記事