Django:DataFrameを配列(リスト)にしてDBに格納する時の注意事項

Django:DataFrameを配列(リスト)にしてDBに格納する時の注意事項

Django:DataFrameを配列(リスト)にしてDBに格納する時の注意事項

CSVデータをDBに取り込む時どうしてますか。
CSVの構造をそのまま(計算処理と化しないで)DBに持っていくのであれば、DataFrameに格納して【to_sql】で投げてしまうのが一番簡単です。が、今回はDataFrame化した値をリストで引き取って計算して統制してDBにSaveするという面倒な段取りを踏んだ時の注意事項です。

問題はDataFrameに格納したときに発生している

DataFrameに格納すると下記2点の問題が発生します。

  1. フィールド型が勝手に割り振られる ※int にしたいのに float になったりなど
  2. 空白にnanが割り当てられる

フィールド型が勝手に割り振られる

例えばJANコードの列が存在していた場合、この列は高確率でfloat が割り当てられます。

CSVデータの中でダブルクォーテーションで囲っている場合はこの限りではないのですが、13桁の数字のみであった場合、私の実験では100% floatとなりました。JANのお尻に【.0】が付いていると言う不思議な構成です。

これを解決するには、pd.read_csv 実行の際にdtypeを指定してあげます。

dtypeは辞書型で作成して配置します。
要素名と要素数が状況によって変わる場合は ifで状況分類をする方法以外にこんな手段もあります。

辞書型を配置せずにobjectとだけ記載しました。
こうする事で、すべての値を一度文字列として所得し格納すます。
その後 .astype(float) などで適切な型に変更すれば、要素数のコントロール不要となり関数を外に配置することも可能です。

空白にnanが割り当てられる

DataFrameは何もしなければデータ欠損をnanで埋めてくれます。
でも、DataFrameをリストに変換するとnanという値が入ったカラムが出来上がります。
テキスト上では2つの回避方法(欠損値の穴埋め方法)があります。

  1. na_values の設定
  2. df.fillna()の利用

na_values の設定

pandas.read.csv の実行時に na_values の設定をするのですが、私の環境ではなぜか動作しませんでした。

df.fillna()の利用

fillnaコマンドは nan の値に指示した値を置換してくれます。
df = df.fillna(‘–‘) と書いてしまうと大本の変数df を置換できず【 nan 】が表示され続けますので注意しましょう。

エラー:Must specify a fill ‘value’ or ‘method’.

今回の記事を記載しようと思った切っ掛けです。
チョット考えれば分かるのですが、DataFrameではNullもNoneも欠損値の記号ではありません。
DataFrameの欠損値はあくまでもnanが記号となります。

つまりこんなコードを書いてしまうと上のエラー(Must specify a fill ‘value’ or ‘method’.)が発生します。

そのためDataFrameに格納した値をリスト化した場合、高確率で欠損値には【nan】が入っていることになります。

指定カラムにnanが入っている場合Noneに置き換えてDBに渡せばDB側でNULLを登録できる

場合分けなのでIF文を使います。

注目ポイントは6行目【 str(data[li]) == ‘nan’ 】

ついつい【data[li] == ‘nan’ 】としてしまいますが、DataFrame上で該当の値は 『nan』となっており『’nan’』ではありません。そのため【 .tolist() 】でリスト化した値も『nan』となっています。
つまり【data[li] == ‘nan’ 】では一致が発生しません。

一致を取得するためにはdata[li] にstr()を掛けて文字列にしたうえで == ‘nan’ でifに掛ける必要があります。
チョットした事なんですけど、忘れがちなんですよね。

まとめ

今回の例のようなNanをMySQLの数値カラムに渡してしまった場合、100%エラーです。
(文字列の様に登録はしてくれません)

バックエンド弄っていて面倒なのは大体【欠損処理】【NULLの処理】【日付処理】です。
これを知っていればバックエンドは怖くない。