やもりの技術ブログ

日々の生活で行った技術的な活動や日頃感じたことを書きます。

【備忘録】8桁のstr型数字 00000000 を pd.read_csv で読み込んだら 0.0 になる罠にハマった話

こんにちは、やもり(yamori-tech)です。

備忘録として「8桁のstr型数字 00000000 を pd.read_csv で読み込んだら 0.0 になる罠にハマった話」について書こうと思います。

結論としては、dtype=object を指定することで、空欄を維持したまま csv を読み込むことができます。

>|python|
pd.read_csv('hoge.csv', dtype=object, encoding='utf-8')
||<

何があったの?

データ処理のため、データベースからデータを一時的にごっそりcsvファイル(hoge.csv)にしたあと、処理しやすくするため、v1.csv, v2.csv と単純に分割していました。そんな時…。

  • DBにこんなデータがあったとき。。
    id col1 col2 col3
    1 11 0000 0000000
    2 15 0000 0000000
    3 14 0000 0000000
    4 17 0000 0000000
    5 21 0000 0000000
  • DB -> hoge.csv へダウンロード、この時点で hoge.csv の col3 には 00000000(文字列)で格納
  • hoge.csv を v1.csv、v2.csv などへ分解すると、v1.csv、v2.csv の col3 は
    0(int) で保存

になる罠にハマってしまいました。。

0000(文字列)は、0000 として エクセル上では 保存されているのになぜなのか?

※ 環境によっては、0000 も 0 になるようです。

f:id:yamori-tech:20210212231358p:plain

colab結果

色々試したのですが、業務用環境では、read_csv を使って、col3 に格納されているような 8桁の0の文字列「00000000」を読み込むと、0 として認識してしまうようでした。 

 

処理上の制限と解決手段

処理上の制限として、

  • 00000000 の文字列があるデータファイルが存在する前提で、レガシースクリプトが動いている
  • 時間の関係で、レガシースクリプトは改修できない
  • そもそもデータベースと同じ値を再現できていない時点で問題あり

ということで、00000000 のまま出力する必要がありました。

 

解決手段としては、

  • col2, col3 を str 変換し、replace してしまう
    → しかし、空部分を、None、NaN等で変換してしまう
    → レガシースクリプトでは、空部分は空として与えなくてはならない

というわけで、公式ドキュメントを再度読むと。。

pandas.pydata.org

f:id:yamori-tech:20210212232304p:plain

f:id:yamori-tech:20210212232326p:plain

適切なna_valuesを維持するために、dtype に object か str を指定したら良いよ!と書いてあるので、指定してみると。。

f:id:yamori-tech:20210212232647p:plain

result

想定していた出力になりました。

dtype は 辞書型にすることで、カラムごとに読み込み形式を指定することもできます。

f:id:yamori-tech:20210212235127p:plain

00, 001 等を読み込むために、read_csv で dtype = str or object を今後は使っていこうと思います。