今回は、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関数を使いこなすことで、整合性のない汚いデータをクリーンアップすることができる。