pythonでcsvを読み込む際どんなAPIを使っていますか?
fileオブジェクトを使う方法、標準ライブラリのcsvモジュールを使う方法、pandasのread_csv関数を使う方法がメジャーだと思います。
これらの方法はどのような問題意識から開発された機能で、どのように使い分けるべきなのでしょうか?
この記事では上記3つの機能を1. パースするか、2. コンテナオブジェクトを自動で作成するかの基準から考察します。
パースしない | パースする | |
---|---|---|
コンテナオブジェクトを作成しない | fileオブジェクト | csv.readerオブジェクト |
コンテナオブジェクトを作成する | -- | pandas.read_csv |
ファイルオブジェクトを利用する方法
最も素朴な方法はファイルオブジェクトのreadlineメソッドを利用する方法です。
この方法では行の終端記号はreadline側で判断してくれますが、
各行を列で分割する部分は自分で開発する必要があります。
data = []
with open("myfile.csv", "r") as f:
rows = f.readlines()
row = rows.next() #ヘッダを飛ばしたい場合
for row_str in rows:
row = row_str.split(",") #文字列中の , でも分割される
data.append(row)
上記の例で上手くいく場合もありますが、データ中の文字列にカンマが含まれる場合は文字列中のカンマでも分割されてしまいます。
この問題に対する一般的な対策は、あらかじめ文字列データの始まりと終わりにダブルクォーテーション"をつけておき、
ダブルクォーテーションに囲まれていないカンマで分割する方法です。
わざわざこの対策を実装するだけでも大変ですが、それに加えて文字列の中に引用符が入っている場合の対策もしなければいけません。
csvモジュールでパース
csvモジュールでは上記のようなカンマ、引用符に対する対策を自動で実施してくれます。
import csv
data = []
with open(file_name, "r") as file_obj:
reader = csv.Reader(file_obj)
reader.next() #ヘッダを飛ばしたい場合
for row in reader:
data.append(row)
csvモジュールを利用することで、簡単に頑健なcsv読み取り機構を構築できます。
ここでは割愛しますが、csvモジュールはcsvの様々な方言に対応できる上に、方言の自動判定をするSnifferというクラスも実装されています。
csvモジュールによってパースを自分で実装する負担がなくなりましたが、
それでもデータ構造(今回はリスト)を自分で構築したりファイルオブジェクトを作成したりといった本質的でない部分によって
8行記述することになってしまいます。
pandasで簡単にデータフレームを作成
pandasのread_csv関数を使うとデータフレームの作成も実装する必要がなくなります。
import pandas as pd
data = pd.read_csv("myfile.csv") #dataはpandasのデータフレームオブジェクト