自主課題(ということにしておきましょう。オシゴトでポチョポチョやっている開発で、どうするかなあと考えていて、家に帰って作った)。
課題
2つのデータフレームを比較したい。2つのデータフレームの行と列は共通だが、1つのデータフレームには欠損値が含まれている。欠損値があると比較できないので、前処理のひとつとして、片方の欠損値の位置をもう片方に反映する。
実行結果
raw_df1
は欠損のないデータフレームで、raw_df2
は欠損のあるデータフレーム。欠損値 Nan
は、位置 (1, 2), (2, 1), (3, 0) にある。
df1
は欠損位置を反映した後のデータフレーム。位置 (1, 2), (2, 1), (3, 0) が Nan
になっている。
なお、df2
は raw_df2
のまま。
$ python mask_nan_pandas.py raw_df1: 0 1 2 0 1.0 2.0 3.0 1 1.0 2.0 3.0 2 1.0 2.0 3.0 3 1.0 2.0 3.0 raw_df2: 0 1 2 0 2.0 4.0 6.0 1 2.0 4.0 NaN 2 2.0 NaN 6.0 3 NaN 4.0 6.0 -------------------- df1: 0 1 2 0 1.0 2.0 3.0 1 1.0 2.0 NaN 2 1.0 NaN 3.0 3 NaN 2.0 3.0 df2: 0 1 2 0 2.0 4.0 6.0 1 2.0 4.0 NaN 2 2.0 NaN 6.0 3 NaN 4.0 6.0
メモ:欠損値 np.nan
かどうかを判定する
欠損値同士を
==
で比較してもFalse
となってしまうため、欠損値かどうかを判定するにはnp.isnan()
かmath.isnan()
を使う。
👉 NumPyの配列ndarrayの欠損値np.nanを他の値に置換 | note.nkmk.me
メモ:df.itertuples()
で行ごとに読む
参考 👉 pandas.DataFrameのforループ処理(イテレーション) | note.nkmk.me
for i, row in enumerate(df.itertuples()): print(row)
↓
Pandas(Index=0, _1=2.0, _2=4.0, _3=6.0) Pandas(Index=1, _1=2.0, _2=4.0, _3=nan) Pandas(Index=2, _1=2.0, _2=nan, _3=6.0) Pandas(Index=3, _1=nan, _2=4.0, _3=6.0)
コード
もっとスマートでシンプルなやり方があるんじゃないかと思いつつ、分からなくてこうなった。
# mask_nan_pandas.py import numpy as np import pandas as pd # 生のデータフレームを作る def make_df(): df1 = pd.DataFrame({\ '0':[1, 1, 1, 1],\ '1':[2, 2, 2, 2],\ '2':[3, 3, 3, 3]\ }, dtype=np.float32) df2 = pd.DataFrame({\ '0':[2, 2, 2, np.nan],\ '1':[4, 4, np.nan, 4],\ '2':[6, np.nan, 6, 6]\ }, dtype=np.float32) return df1, df2 # データフレーム内の欠損値を探し、リストで返す def get_iloc_nan(df): iloc_nan_list = [] for i, row in enumerate(df.itertuples()): for j, value in enumerate(row[1:]): if np.isnan(value): iloc_nan_list.append((i, j)) return iloc_nan_list # 位置を指定して NaN で置き換える def mask(df1, df2): for locat in get_iloc_nan(df2): df1.iloc[locat[0], locat[1]] = np.nan return df1, df2 if __name__ == '__main__': raw_df1, raw_df2 = make_df() print('raw_df1:\n', raw_df1, '\n') print('raw_df2:\n', raw_df2, '\n') print('-'*20) df1, df2 = mask(raw_df1, raw_df2) print('df1:\n', df1, '\n') print('df2:\n', df2, '\n')