こんにちは。現役Webエンジニアの三年坊主です。
今回は、Pythonでcsvファイルを読み込みたい人の、このような疑問に答えます。
この記事では、大学の研究と自分の趣味で、合わせて5年以上Pythonを使ってきた経験を生かして、標準のcsvモジュールを使ってPythonでcsvファイルを読み込む方法を紹介します。
この記事の内容
- csvとは
- 読み込むcsvファイルを用意する
- Pythonでcsvファイルの読み込み
- Pythonで読み込んだcsvデータの扱い方
- csvデータにカンマが含まれる?
csvとは?
csvは、”Comma-Separated Values“の略です。
つまりcsvファイルというのは、項目をカンマ(,)で区切ったテキストファイルのことをさします。
タブで区切っていたらtsvファイル “Tab-Separated Values” と呼んだりします。

読み込むcsvファイルを用意する
csvファイルは、世の中のいろいろなところで活用されています。
ほんの一例ですが、クレジットカードの利用履歴をcsvファイルとしてダウンロードできる会社もあるようです。
今回はためしに、エポスカードの利用履歴を使ってみることにします。フォーマットはこのような感じです。


nkfコマンドでファイルの文字コードを確認すると、Shift_JISのようでした。
1 | nkf --guess 20181006_UseHistoryReference_sample.csv |
Pythonでcsvファイルの読み込み
Pythonでcsvファイルを読み込む処理の流れはこんな感じです。
- (1) csvモジュールをインポート
- (2) csvファイルを開く
- (3) 開いたcsvファイルからreaderオブジェクトを作成する
- (4) readerオブジェクトを使って一行ずつデータを取得する
- (5) csvファイルを閉じる
(1) csvモジュールをインポート
標準ライブラリからcsvモジュールをインポートします。
このライブラリはcsvファイル専用というわけではなく、delimiter(あとで説明)を変えたりして、様々なフォーマットに対応できます。
ファイル名も変数に入れておきましょう。
1 2 3 | import csv file_path = '20181006_UseHistoryReference_sample.csv' |
(2) csvファイルを開く
組み込み関数 open() を使って、ファイルを読み込み用に開きます。
csvfile がファイルオブジェクトの場合、 newline=” として開くべきです。
ファイルの文字コードも指定しましょう。今回は、encoding=’shift_jis’ と指定します。
7.2.3. 標準エンコーディングに書いてあるように、csshiftjis, shiftjis, sjis, s_jisなどの別名を使っても大丈夫です。
1 | csvfile = open(file_path, 'r', newline='', encoding='shift_jis') |
(3) readerオブジェクトを作成
ヘッダーを読み飛ばしたいとき、header = next(csv_reader) を使って、ヘッダーの次の行をさすようにします。
1 2 | csv_reader = csv.reader(csvfile) header = next(csv_reader) |
(4) 一行ずつデータを取得
readerオブジェクト(csv_reader)を使って、一行ずつリスト形式でファイルの中身を読み込みます。print文で中身を確認してみましょう。
1 2 | for row in csv_reader: print(row) |
1 2 | ['ショッピング', '2018年10月1日', 'スイドウリョウキンゲスイ', '−', '4246', '1回払い', '2018年11月', ''] ['ショッピング', '2018年10月4日', 'ファミリーマート', '−', '108', '1回払い', '2018年11月', ''] |
(5) csvファイルを閉じる
openしたファイルを忘れずにcloseしましょう。
1 | csvfile.close() |
(1)〜(5)を通して実行する
1 2 3 4 5 6 7 8 9 10 11 12 | import csv file_path = '20181006_UseHistoryReference_sample.csv' csvfile = open(file_path, 'r', newline='', encoding='shift_jis') csv_reader = csv.reader(csvfile) header = next(csv_reader) for row in csv_reader: print(row) csvfile.close() |
1 2 | ['ショッピング', '2018年10月1日', 'スイドウリョウキンゲスイ', '−', '4246', '1回払い', '2018年11月', ''] ['ショッピング', '2018年10月4日', 'ファミリーマート', '−', '108', '1回払い', '2018年11月', ''] |
with構文を使って少し楽をする【コピペ用】
with構文を使うと、ファイルのクローズを自動的に行えるので、csvファイルの読み込みをよりシンプルに書くことができます。
1 2 3 4 5 6 7 8 9 10 | import csv file_path = '20181006_UseHistoryReference_sample.csv' with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: csv_reader = csv.reader(csvfile) header = next(csv_reader) for row in csv_reader: print(row) |
1 2 | ['ショッピング', '2018年10月1日', 'スイドウリョウキンゲスイ', '−', '4246', '1回払い', '2018年11月', ''] ['ショッピング', '2018年10月4日', 'ファミリーマート', '−', '108', '1回払い', '2018年11月', ''] |
おまけ:readerオブジェクトって何?
ファイルの「読み込み方」と「読み込み状態」を保持しておくオブジェクトです。読み込みに関していえば、中身(属性)は主にこの2つ。
- dialect:方言を設定する。「方言」はつまり「ファイルをどうやって読み込むのか」のことで、「フィールド間を区切る文字」や「改行の取り扱い方」などをまとめたものを方言と呼んでいます。
- line_num:すでに読み込んだ行数
が設定されています。
一行読み込むごとに、line_numの値が1ずつ増えているのが分かります。1がないのは、header = next(csv_reader)で一行読み飛ばしているからですね。
1 2 3 4 5 6 7 8 9 10 | with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: csv_reader = csv.reader(csvfile) header = next(csv_reader) print(csv_reader.dialect) for row in csv_reader: print(row) # すでに読み込んだ行数 print(csv_reader.line_num) |
1 2 3 4 5 | <_csv.Dialect object at 0x7efefcf758b8> ['ショッピング', '2018年10月1日', 'スイドウリョウキンゲスイ', '−', '4246', '1回払い', '2018年11月', ''] 2 ['ショッピング', '2018年10月4日', 'ファミリーマート', '−', '108', '1回払い', '2018年11月', ''] 3 |
csv.reader と csv.DictReader
これまで見てきたように、csv.readerを使うと、各行をリスト形式で読み込めます。
1 2 3 4 5 6 7 | with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: # リスト形式 csv_reader = csv.reader(csvfile) header = next(csv_reader) for row in csv_reader: print(row) |
1 2 | ['ショッピング', '2018年10月1日', 'スイドウリョウキンゲスイ', '−', '4246', '1回払い', '2018年11月', ''] ['ショッピング', '2018年10月4日', 'ファミリーマート', '−', '108', '1回払い', '2018年11月', ''] |
一方で、csv.DictReaderを使うと、各行を辞書形式で読み込めます。
1 2 3 4 5 6 | with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: # 辞書形式 csv_dictreader = csv.DictReader(csvfile) for row in csv_dictreader: print(row) |
1 2 | OrderedDict([('種別', 'ショッピング'), ('ご利用年月日', '2018年10月1日'), ('ご利用場所', 'スイドウリョウキンゲスイ'), ('ご利用内容', '−'), ('ご利用金額', '4246'), ('支払区分', '1回払い'), ('お支払開始月', '2018年11月'), ('備考', '')]) OrderedDict([('種別', 'ショッピング'), ('ご利用年月日', '2018年10月4日'), ('ご利用場所', 'ファミリーマート'), ('ご利用内容', '−'), ('ご利用金額', '108'), ('支払区分', '1回払い'), ('お支払開始月', '2018年11月'), ('備考', '')]) |
csv.readerと比べたメリット
- header = next(csv_reader)でヘッダーを読み飛ばす必要がない
- ヘッダーとデータの対応が分かりやすい(「ご利用場所」が「ファミリーマート」だとすぐにわかる)
Pythonで読み込んだcsvデータの扱い方
csv.readerを使う【コピペ用】
csv.readerを使って、各行をリスト形式で読み込みます。
row
1 2 3 4 5 6 7 8 9 10 11 12 | data_list = [] with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: # リスト形式 csv_reader = csv.reader(csvfile) header = next(csv_reader) for row in csv_reader: # 欲しいデータだけ使う use_date, use_place, use_amount = row[1], row[2], row[4] data_list.append((use_date, use_place, use_amount)) print(data_list) |
1 | [('2018年10月1日', 'スイドウリョウキンゲスイ', '4246'), ('2018年10月4日', 'ファミリーマート', '108')] |
csv.DictReaderを使う【コピペ用】
csv.DictReaderを使って、各行を辞書形式で読み込みます。
row[‘ご利用年月日’]のように、必要な項目にアクセスして使います。
1 2 3 4 5 6 7 8 9 10 11 | data_list = [] with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: # 辞書形式 csv_dictreader = csv.DictReader(csvfile) for row in csv_dictreader: # 欲しいデータだけ使う use_date, use_place, use_amount = row['ご利用年月日'], row['ご利用場所'], row['ご利用金額'] data_list.append((use_date, use_place, use_amount)) print(data_list) |
1 | [('2018年10月1日', 'スイドウリョウキンゲスイ', '4246'), ('2018年10月4日', 'ファミリーマート', '108')] |
csvデータにカンマが含まれる?
“4,246”
のように、金額の数字にカンマが入っているとき、delimiterに「区切り文字」、quotecharに「囲い文字」を指定して、データの中身と区切り文字を区別できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 | file_path = '20181006_UseHistoryReference_sample_comma.csv' data_list = [] with open(file_path, 'r', newline='', encoding='shift_jis') as csvfile: # 辞書形式 csv_dictreader = csv.DictReader(csvfile, delimiter=',', quotechar='"') for row in csv_dictreader: # 欲しいデータだけ使う use_date, use_place, use_amount = row['ご利用年月日'], row['ご利用場所'], row['ご利用金額'] data_list.append((use_date, use_place, use_amount)) print(data_list) |
1 | [('2018年10月1日', 'スイドウリョウキンゲスイ', '4,246'), ('2018年10月4日', 'ファミリーマート', '108')] |
Pythonでcsvファイルを読み込んで、快適なエンジニア生活を送りましょう。