この記事ではデータの欠落において、pandasがそれを表現する方法についてや処理の方法についてを解説します。
目次
Udemyの動画学習でもPythonを勉強しよう!
「平日の夜の勉強会には時間が間に合わなくて参加できない」「通勤時間のわずかな隙間時間を勉強時間にあてたい」「本ではよく分からないところを動画で理解を深めたい」そんなあなたはUdemyの動画学習がお勧めです!
UdemyのPythonおすすめ33講座レビューリストpandasでデータ分析を行うときにデータが欠落していると、分析結果に影響を与える可能性があります。この記事を読んで、データの欠損に対処する方法について学びましょう。
pandasについて
pandasを使うと、データの統計量を表示したり、グラフ化するなど、データ分析(データサイエンス)や機械学習で必要となる作業を簡単に行うことができるようになります。
pandasは外部ライブラリなので、使用するにはインストールが必要になります。Numpyの記事でも取り上げましたが、インストールにはAnacondaやminicondaがおすすめです。
pandasの欠損値の検出
csvファイルをpandasで読み込んだとき、要素が空白だったりすると欠損値NaN(Not a Number)だとみなされます。その際におけるNaNの扱いについて説明します。
今回のデータセットは以下のものを使います。5人の生徒の5教科のテスト結果をDataFrameにしています。欠損値はnp.nanによって生成しています。pandasではnp.nanはnoneを使っても同じように処理することができます。
data = pd.DataFrame(np.array([[80, 70, 80, 90, np.nan], [60, 60, 60, 60, 60], [np.nan, 80, 70, 60, np.nan], [40, np.nan, 40, 80, 80], [50, 80, np.nan, 50, 80]]), columns=["Math", "English", "Physics", "Chemistry", "History"], index=["Tanaka", "Suzuki", "Sato", "Yamada", "Ogawa"])# Math English Physics Chemistry History# Tanaka 80.0 70.0 80.0 90.0 NaN# Suzuki 60.0 60.0 60.0 60.0 60.0# Sato NaN 80.0 70.0 60.0 NaN# Yamada 40.0 NaN 40.0 80.0 80.0# Ogawa 50.0 80.0 NaN 50.0 80.0
pandasのデータ構造には、NaNを検出するための2つのメソッドisnull()とnotnull()が用意されています。いずれも、データに対するブール値(TrueもしくはFalse)が返されます。例を見てみましょう。NaNの要素にはTrueが、それ以外にはFalseが返されていることが確認できます。
print(data.isnull())
# Math English Physics Chemistry History
# Tanaka False False False False True
# Suzuki False False False False False
# Sato True False False False True
# Yamada False True False False False
# Ogawa False False True False False
notnull()はisnull()の逆です。NaNの要素にはFalseが、それ以外にはTrueが返されていることが確認できます。以下のように
print(data.notnull())
# Math English Physics Chemistry History
# Tanaka True True True True False
# Suzuki True True True True True
# Sato False True True True False
# Yamada True False True True True
# Ogawa True True False True True
pandasの欠損値の除外
pandasにおける欠損値を除外するにはdropna()を使います。Seriesに対する結果は単純です。
series = pd.Series([1, np.nan, 'hello', np.nan])
print(series)
# 0 1
# 1 NaN
# 2 hello
# 3 NaN
# dtype: object
次にDataFrameについて考えてみましょう。DataFrameは先程のものを使います。
print(data)
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 NaN
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Sato NaN 80.0 70.0 60.0 NaN
# Yamada 40.0 NaN 40.0 80.0 80.0
# Ogawa 50.0 80.0 NaN 50.0 80.0
DataFrameは行と列からなるので1つの要素を削除することはできません。まずデフォルトでは、dropna()はNaNが存在する全ての行を削除します。今回の例ではテスト結果に欠損値のないSuzukiの結果が返されます。
print(data.dropna())
# Math English Physics Chemistry History
# Suzuki 60.0 60.0 60.0 60.0 60.0
または別の軸に沿ったNaNの除外も可能です。引数axisを指定することで、NaNを含む全ての列を削除します。今回の例では欠損値のないChemistyの結果が返されます。
print(data.dropna(axis='1'))
# Chemistry
# Tanaka 90.0
# Suzuki 60.0
# Sato 60.0
# Yamada 80.0
# Ogawa 50.0
除外対象にする行や列を要素がすべてNaNのときに限定したいかもしれません。そのときは、引数how=’all’を指定すると全ての値が欠損値の行が削除されます。
また、引数threshに個数を指定すると欠損値ではない要素の数に応じて行や列を削除することができます。今回の例だとthresh=4とすると欠損値ではない要素の数がが4つ以上含まれている行が残ります。
print(data.dropna(thresh=4))
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 NaN
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Yamada 40.0 NaN 40.0 80.0 80.0
# Ogawa 50.0 80.0 NaN 50.0 80.0
さらに特定の行や列にしぼって削除したい場合は、引数subsetに対象としたい行列のラベルを指定します。今回はHistoryに欠損値がある場合その行を削除します。
print(data.dropna(subset=['History']))
# Math English Physics Chemistry History
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Yamada 40.0 NaN 40.0 80.0 80.0
# Ogawa 50.0 80.0 NaN 50.0 80.0
pandasの欠損値の置換
NaNを有効な値で置き換えることがいい場合もあります。NaNを全て0で置き換えるように単一の数値を使ったり、他の適当な値から補完をすることができます。
そんなときはfillna()を使うことで欠損値を任意の値で置き換えることができます。
先程のdataを例とします。
print(data)
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 NaN
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Sato NaN 80.0 70.0 60.0 NaN
# Yamada 40.0 NaN 40.0 80.0 80.0
# Ogawa 50.0 80.0 NaN 50.0 80.0
dataの欠損値をすべて0で置き換えてみます。
print(data.fillna(0))
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 0.0
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Sato 0.0 80.0 70.0 60.0 0.0
# Yamada 40.0 0.0 40.0 80.0 80.0
# Ogawa 50.0 80.0 0.0 50.0 80.0
引数method=’ffill’ (forward fill)を指定することで、NaNの要素に対して1つ前の値を埋めることができます。forward fillを行うとき前の値を利用できない場合はNaNが残ります。
print(data.fillna(method='ffill'))
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 NaN
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Sato 60.0 80.0 70.0 60.0 60.0
# Yamada 40.0 80.0 40.0 80.0 80.0
# Ogawa 50.0 80.0 40.0 50.0 80.0
軸の指定をすることもできます。今回の例の場合は、1列目がNaNの場合残ってしまいます。
print(data.fillna(method='ffill', axis=1))
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 90.0
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Sato NaN 80.0 70.0 60.0 60.0
# Yamada 40.0 40.0 40.0 80.0 80.0
# Ogawa 50.0 80.0 80.0 50.0 80.0
同じように引数method=’bfill’ (back fill)を指定することでNaNの要素に対して1通白の値を埋めることができます。この場合は最後の行のNaNは残ってしまいます。
print(data.fillna(method='bfill'))
# Math English Physics Chemistry History
# Tanaka 80.0 70.0 80.0 90.0 60.0
# Suzuki 60.0 60.0 60.0 60.0 60.0
# Sato 40.0 80.0 70.0 60.0 80.0
# Yamada 40.0 80.0 40.0 80.0 80.0
# Ogawa 50.0 80.0 NaN 50.0 80.0
まとめ
今回はpandasにおける欠損値の扱いについて解説しました。欠損値をうまく処理することでよりpandasを使いこなすことができるようになると思うのでぜひマスターしましょう。
Udemyの動画学習でもPythonを勉強しよう!
「平日の夜の勉強会には時間が間に合わなくて参加できない」「通勤時間のわずかな隙間時間を勉強時間にあてたい」「本ではよく分からないところを動画で理解を深めたい」そんなあなたはUdemyの動画学習がお勧めです!
UdemyのPythonおすすめ33講座レビューリスト