KNIMEとか倉庫

KNIMEやEXCELなどの備忘録です。

【Python】欠損値を何とかしたい

・お題:データセット中の欠損値の有無などを調べて、何とかしたい。

 

・入手したデータが、端から端までピッチリ埋まっていることは、実験データを収集するうえで期待できない場合が多い。入手したデータセットの欠損値に関して情報を得て、何とかしたい。

・とりあえず、データセットを作る。

import pandas as pd
import numpy as np
import random

a=np.random.rand(15)
b=[i + np.random.normal(0,0.1) for i in a]
df=pd.DataFrame({"A":a,"B":b})

#dfはA列に15個、B列に15個データがピッチリ入ったデータセット。ここから欠損を含むデータセットdf2を作成する。

df2=df.copy()
mask=np.random.choice([0,1],p=[0.2,0.8],size=df2.shape[0]*df2.shape[1]).reshape(df2.shape[0],df2.shape[1]).astype(bool)#2割程度を欠損値にしたい。
df2=df2.where(mask, np.nan)

df2["C"]=[i*(-1.3) + np.random.normal(0,0.2) for i in a]#さらに、欠損値を含まない15個のデータが入ったC列を追加した。

・df2の中身は以下の通り。

・どこに何個データが入っているか知りたい。

df2.info()

を実行すると、

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   A       11 non-null     float64
 1   B       12 non-null     float64
 2   C       15 non-null     float64
dtypes: float64(3)
memory usage: 488.0 bytes

が返ってくる。15の行があり、A列には11個、B列には12個、C列には15個ののfloat64が入っている。

・どこに欠損値があるのか、何個欠損値があるのか知りたい。

df2.isna()

すると、

が返ってくる。df2.isnull()でも同じ結果になる。df2.notna()だとTrueとFalseが逆になる。~で反転させても良いので、この辺は気分だと思う。

どの列に何個欠損値があるのか調べたい場合、

df2.isna().sum()

すると

A    4
B    3
C    0
dtype: int64

が返ってくる。Trueが1でFalseが0なので、sumすればTrueを数えることになるっぽい。今回は欠損値がTrueなので、欠損値の数が返ってくる。欠損値が入っているのかどうかを調べたい場合、df2.isna().any()すれば、欠損値のある列はTrue、欠損値のない列はFalseが返ってくる。

・欠損値の入った行を消したい。

mask=df2.isna().sum(axis=1).astype(bool)#1つでも欠損値があるとTrueになる。

df2[-mask]

で、欠損値が一つでもある行が取り除かれ、以下が返ってくる。

わざわざこんなことしなくても、df2.dropna()で欠損値の入った行を取り除くことができる。また、引数にaxis=1を入れれば欠損値の入った行を除去でき、thresh=を入れれば除外する行の欠損値の閾値を設定できる。便利。

・欠損値を何かで埋めたい。

df2.fillna(引数)

で、欠損値を引数で埋めることができる。

この引数には辞書を入れることもでき、列名をキーとして辞書の対応する値を挿入できる

dic={"A":1,"B":10,"c":100}
df2.fillna(dic)

とすると、

が返ってくる。

前後の数の算術平均値で埋める場合は、

df2.interpolate()

とすればいいかが返ってくる。

A列の1行と2行は続きの欠損値だったが、さらにその上下の数の等差数列のようになった。順序をもとに埋められそうな変数なら、このような埋め方も有効なのかもしれない。

 

・欠損値の有無や数を調べることは当然必要だが、難しいのはそれを知ってどう対処すべきなんだろうなぁ、と感じた。

 

おわり。