内容間違ってます。正しい内容はコメントにあり
正しい内容はこちらとこちら。両方ともこの投稿へのコメントです。
以下、記事の内容は間違っていますが、誰かが同じ勘違いをしてもこれを読んでミスに気づくよう残しておきます。
CSVモジュールはpandasの数10倍速い?
読書記録をつけるため、csvファイルに1行ずつ追記していく単純な関数をPython3で作りました。pythonでは標準ライブラリにcsvモジュールがあるほか、pandasでもcsvに書き出せるということで、速度計測しました。
%%timeit
from time import strftime
import pandas as pd
def readlog(title=None, impression=None, key=None, page=0, author=None, time=strftime('%Y/%m/%d'), url=None):
df = pd.DataFrame([title,impression,key,page,author,time,url]).T
df.to_csv('readlog.csv', mode='a', header=False)
readlog(title='monty', impression='awesome', author='python', key='Spanish Inquisition')
# 1000 loops, best of 3: 878 µs per loop
%%timeit
import csv
from time import strftime
def rdlog(title=None, impression=None, key=None, page=0, author=None, time=strftime('%Y/%m/%d'), url=None):
with open('rdlog.csv', mode='a') as f:
writer = csv.writer(f)
writer.writerow([title, impression, key, page, author, time, url])
rdlog(title='monty', impression='awesome', author='python', key='Spanish Inquisition')
# 10000 loops, best of 3: 26.3 µs per loop
結果は
pandas
1000 loops, best of 3: 878 µs per loop
csvモジュール
10000 loops, best of 3: 26.3 µs per loop
Pandasを使いこなせてない可能性
pandasでググると、実行速度を爆速化する方法を説明した記事が複数個ヒットしたので、単に下手な使い方をしているだけかもしれません。
またあとで確認したいと思います。
##追記
pd.DataFrameのインスタンス生成がオーバーヘッドになっているとのご指摘を受けたのでチェック。比べると確かに重い…!
%timeit df = pd.DataFrame(['a', 'awesome', '23', None]).T
# 1000 loops, best of 3: 344 µs per loop
%timeit lst = ['a', 'awesome', '23', None]
# 10000000 loops, best of 3: 103 ns per loop
オーバーヘッドはここだけ?→間違い判明
では、この箇所以外は問題ないかと言うと、そうでもありませんでした。
pd.DataFrame.to_csvもまた、csvモジュールよりベストな結果では30倍遅いという結果に(下記3と4)。計測方法などに不備がありましたら、お知らせください。すごく助かります。
以下、コードとその下に %timeitの計測結果です。
- DataFrameからリストに変換して、csvモジュールで書き込み。セル全体の実行時間を計測。
- リストからDataFrameに変換して、pd.DataFrame.to_csvで書き込み。セル全体の実行時間を計測。
- csvモジュールで書き込みだけする関数を作り、実行時間を計測。
- pd.DataFrame.to_csvの実行時間を計測。
%%timeit
df = pd.DataFrame(['a', 'awesome', '23', None])
lst = df.values.tolist()
with open('test.csv', mode='a') as f:
writer = csv.writer(f)
writer.writerow(lst)
# 1000 loops, best of 3: 285 µs per loop
1000 loops, best of 3: 285 µs per loop(DataFrame→List)
%%timeit
lis = ['a', 'awesome', '23', None]
df = pd.DataFrame(lis).T
df.to_csv('pdtest.csv', 'a')
# 1000 loops, best of 3: 1.01 ms per loop
1000 loops, best of 3: 1.01 ms per loop(List→DataFrame)
%timeit df.to_csv('pdtest.csv', 'a')
# 1000 loops, best of 3: 613 µs per loop
1000 loops, best of 3: 613 µs per loop(pd.DataFrame.to_csv)
def csvopen():
with open('test.csv', mode='a') as f:
writer = csv.writer(f)
writer.writerow(lst)
%timeit csvopen()
# 10000 loops, best of 3: 22.2 µs per loop
10000 loops, best of 3: 22.2 µs per loop(csvモジュール)