今回は、pandasデータフレームのlocを用いた欠損値の補完についての応用的な使い方を紹介する。
サンプルデータフレームの用意
サンプルとして以下のようなデータフレームを用意した。
単純な売上データをデータフレーム化したものだ。
import pandas as pd import numpy as np df = pd.DataFrame([ ['2019-11-01 00:00:00', 'item_a', 2000], ['2019-11-02 00:00:00', 'item_b', np.nan], ['2019-11-03 00:00:00', 'item_c', 10000], ['2019-11-04 00:00:00', 'item_b', 900], ['2019-11-05 00:00:00', 'item_a', 2000], ['2019-11-06 00:00:00', 'item_c', 10000], ['2019-11-07 00:00:00', 'item_a', np.nan], ['2019-11-08 00:00:00', 'item_a', np.nan], ['2019-11-09 00:00:00', 'item_c', np.nan], ['2019-11-10 00:00:00', 'item_b', 900], ], columns=['purchase_date', 'item_name', 'price']) # purchase_date item_name price # 0 2019-11-01 00:00:00 item_a 2000.0 # 1 2019-11-02 00:00:00 item_b NaN # 2 2019-11-03 00:00:00 item_c 10000.0 # 3 2019-11-04 00:00:00 item_b 900.0 # 4 2019-11-05 00:00:00 item_a 2000.0 # 5 2019-11-06 00:00:00 item_c 10000.0 # 6 2019-11-07 00:00:00 item_a NaN # 7 2019-11-08 00:00:00 item_a NaN # 8 2019-11-09 00:00:00 item_c NaN # 9 2019-11-10 00:00:00 item_b 900.0
このデータフレームの金額情報(price列)にはいくつかの欠損値NaNが含まれている。
今回は、この欠損値を正しい金額で穴埋めする方法を紹介する。
欠損値が含まれている行を調べる
まず、price列に欠損値が含まれている行を調べるため、isnull関数を使って変数に保存しておく。
Trueとなっている行が、金額情報の欠損を表す。
flg_is_null = df['price'].isnull() # 0 False # 1 True # 2 False # 3 False # 4 False # 5 False # 6 True # 7 True # 8 True # 9 False # Name: price, dtype: bool
同じ商品で金額が正しく入った行を利用して補完する
少々ややこしいコードではあるが、for文とlocを使って金額が正しく入力されている行を利用して、欠損値を補完していく。
for trg in list(df.loc[flg_is_null, 'item_name'].unique()): price = df.loc[(~flg_is_null) & (df['item_name'] == trg), 'price'].max() df['price'].loc[(flg_is_null) & (df['item_name'] == trg)] = price # purchase_date item_name price # 0 2019-11-01 00:00:00 item_a 2000.0 # 1 2019-11-02 00:00:00 item_b 900.0 # 2 2019-11-03 00:00:00 item_c 10000.0 # 3 2019-11-04 00:00:00 item_b 900.0 # 4 2019-11-05 00:00:00 item_a 2000.0 # 5 2019-11-06 00:00:00 item_c 10000.0 # 6 2019-11-07 00:00:00 item_a 2000.0 # 7 2019-11-08 00:00:00 item_a 2000.0 # 8 2019-11-09 00:00:00 item_c 10000.0 # 9 2019-11-10 00:00:00 item_b 900.0
データフレームのlocは、任意の条件に合致するデータを抽出する関数だ。
1行目のfor文では、flg_is_nullがTrueの行。
つまり欠損値が含まれている行を抽出し、そのうちitem_nameのみを切り出している。
また、item_nameの重複を排除するようunique関数も併用している。
これで「重複を除く、欠損値が含まれている商品名」を抽出できた。
後はこれをlist関数で配列化し、ループ処理をかけているだけだ。
2行目のlocでは、「~」でTrue/Falseを反転させ、金額が正しく入力されている行を、尚且つ同じ商品名である行を抽出し、その金額を変数priceに保存している。
そして3行目で、欠損値のある行に保存した変数priceを代入し、正しい金額への補完を行っている。
このようにloc関数を使いこなすことで、整合性のない汚いデータをクリーンアップすることができる。