こんにちは、座禅いぬです。今回は、企業協働でデータを触ったときにきっとあるあるだろう話です。後でもうちょっと清書する。
CSVは軽い、という思い込み
データ分析をやっていると、Excelファイル(XLSX)をCSVに変換する場面がよくあります。CSVはプレーンテキストだから軽い、XLSXは色々な情報が入っているから重い。そう思っていました。実際、多くの場合はそうです。
企業協働で大きめのデータセットを受け取ったとき、まずCSVに変換しようとしました。Pythonで読み込んでpandasで処理する予定だったからです。何も考えずに変換して、ふとファイルサイズを見て固まりました。
増えとるやないか
元のXLSXファイルが約125MBだったのに、CSVにしたら約200MBになっていました。軽くなるはずが、重くなっている。最初はミスったかと思って、もう一度変換しました。やっぱり増える。
調べてみると、これは珍しい話ではないようです。XLSXはZIP圧縮されているんです。中身はXMLファイルの集まりで、それがZIPでまとめられている。だから見かけ上は小さく見える。一方CSVはプレーンテキストなので圧縮されていない。展開したら膨らむのは当然といえば当然でした。
数値データが多いと顕著
特に数値データが大量にあるファイルでこの現象が起きやすいようです。数値は圧縮効率が高いので、XLSX内ではコンパクトに格納されています。それをテキストとして展開すると、桁数分の文字列になる。小数点以下の精度が高いデータだと、なおさら膨らみます。
今回のデータセットは医療系の数値データで、小数点以下6桁とかザラにありました。それが数万行。圧縮されていたものが全部テキストになったら、そりゃ増えます。
pandasで読むならどっちが速い?
ファイルサイズは増えたけど、pandasで読み込むときはどうなのか。結論から言うと、CSVの方が速いです。pandas.read_csv()は内部でC言語の高速パーサーを使っていて、プレーンテキストをガーッと読み込みます。一方pandas.read_excel()は、まずZIPを解凍して、XMLをパースして、openpyxlというライブラリを経由して...と処理が多い。同じデータでも読み込み時間が数倍違うことがあります。
メモリ使用量はどうかというと、DataFrameに展開された後は同じです。元がXLSXでもCSVでも、pandas内部での保持形式は変わりません。つまり「ファイルサイズが小さい=メモリ効率がいい」ではない。ディスク上のサイズと、メモリ上のサイズは別物です。
大きなデータを扱うなら、実はCSVよりParquetやFeatherといった列指向フォーマットの方が優秀です。圧縮効率も読み込み速度も良い。ただ、企業からもらうデータは大抵ExcelかCSVなので、まずは変換する必要があります。
学んだこと
この経験から学んだのは、「軽いはず」という思い込みは危険だということです。XLSXがZIP圧縮されているなんて、言われてみれば知っていたはずなのに、実際にファイルサイズを見るまで意識していませんでした。
データを扱う仕事では、こういう「当たり前」を疑う姿勢が大事なんだと思います。変換したら軽くなるはず、ではなく、変換したらどうなるか確認する。特に大きなデータを扱うときは、思い込みがボトルネックになることがあります。
まとめ
XLSXをCSVに変換したらファイルサイズが3倍になった話でした。原因はXLSXのZIP圧縮。数値データが多いファイルでは特にこの現象が起きやすいです。
DXの現場では、こういう小さな「あれ?」の積み重ねが学びになります。教科書には載っていない、実際に手を動かさないとわからないこと。企業協働でデータに触れる機会をもらえたからこそ、体験できました。皆さんもデータを触るときは、色々な発見があるかもしれないです。