Pythonで欠損値や外れ値を除外してデータを綺麗にする方法

スポンサーリンク

機械学習アルゴリズムの効果的な実装や、データセットのデータ解析を行う場合にも、クリーンなデータが必要です。

データによる数値モデリングについて、「Trash in Trash out」という有名な言葉がありますが、データがクリーンでなければ、まともな結果は期待できません。

この記事では、pandasライブラリを使ってデータをきれいにするための一般的なテクニックを探ります。

スポンサーリンク

Common Data Cleaning Checks

以下に基づいてデータをクリーニングします。

  • 欠測値
  • 外れ値
  • 重複する値

1. 欠測値

Pandasでは、欠損値は通常 NaN で表されます。

PandasはNumPyパッケージをベースにしているので、NumPy特有の浮動小数点型のNaN値ということになります。

この記事で使用したデータセットはこちらで確認できます。

欠測値の検出

まず、データ中に欠損値があるかどうかを調べる方法を説明します。

アプローチ1:視覚的に

import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt
 
#importing Dataset
df = pd.read_csv('IMDB-Movie-Data.csv')
 
#Creating the heatmap
plt.figure(figsize = (8,6))
sb.heatmap(df.isnull(), cbar=False , cmap = 'magma')
import pandas as pd
 
#importing dataset
df = pd.read_csv('IMDB-Movie-Data.csv')
 
df.isnull().sum()

.isnull() メソッドは、データ中に欠損値があるかどうかを示す真偽値を返す。

しかし、この処理は中規模から小規模のデータセットに限られる可能性があります。

アプローチ2

.isnull()を適用した後に.sum()` メソッドを使用すると、データフレーム内の各列の欠損値の合計を返すことができます。

#imporing pandas
import pandas as pd
 
#Importing dataset
df = pd.read_csv('IMDB-Movie-Data.csv')
 
#Size of original dataset
print(df.shape)
 
#Dropping the missing rows.
df_dropped = df.dropna(how = 'any')
import pandas as pd
 
#importing the dataset
df = pd.read_csv('IMDB-Movie-Data.csv')
 
#Creating a copy of dataframe
df_new = df
 
df_new['Metascore'] = df_new['Metascore'].fillna((df_new['Metascore'].mean()))
 
#printing the dataframes after replacing null values
print(df_new.isna().sum())
print(df.isna().sum())

データから欠損値を除去する

私たちのデータセットには、いくつかの欠測値があることがわかりました。

私たちは、欠測値を含む行や列を削除するか、欠測値を適切な量(例えば、平均値、中央値、最頻値)に置き換えることができます。

    1. 欠損値を削除する
#importing required modules
import pandas as pd
import numpy as np
from scipy import stats
 
#importing dataset
df = pd.read_csv('IMDB-Movie-Data.csv')
 
#filtering outliers
df_new = df[(np.abs(stats.zscore(df.Votes)) < 3)]

上記のコードでは、データフレームから欠損値を持つ行を削除します。

それでは、.dropna() メソッドを詳しく見ていきましょう。

  • df.dropna() – NaN 値を持つすべての行を削除します。
  • df.dropna(how=’all’) – すべての列がNaNである場合のみドロップします。
  • df.dropna(thresh=2) – NaNでない値が2つ以上ない場合に行を削除します。
  • df.dropna(subset=[1]) – 特定の列にNaNがある場合のみドロップします。

欠損値の削除を検討する場合、データセットの品質に影響を与える可能性があるため、注意が必要です。

  1. 欠損値の置き換え
#importing required modules
import pandas as pd
import numpy as np
from scipy import stats
 
#importing dataset
df = pd.read_csv('IMDB-Movie-Data.csv')
 
#Selecting limits
q_low = df["Votes"].quantile(0.01)
q_hi  = df["Votes"].quantile(0.99)
 
#filtering outliers
df_filtered = df[(df["Votes"] < q_hi) & (df["Votes"] > q_low)]
#Import the required modules
import pandas as pd
import numpy as np
 
#importing and appending similar rows to of the dataframe
df = pd.read_csv('IMDB-Movie-Data.csv')
df1 = df.append(df.iloc[20:30,:])
 
df1.duplicated().sum()

pandas には .fillna() メソッドがあり、NaN 値の代わりに置き換えたい値を受け取ることができます。

ここでは、列の平均を計算し、それを fillna() メソッドの入力引数として渡しました。

2. 外れ値への対応

外れ値は、予測全体の流れを変える可能性があるため、外れ値を検出し、除去することが重要です。

Z-Scoreの使用

データセットのVotes列で外れ値を検出し、Zスコアを使用して外れ値をフィルタリングしてみましょう。

この方法の背後にある考え方は、平均から3標準偏差離れたところにある値を外れ値と呼ぶという事実にある。

#Importing the required modules
#Import the required modules
import pandas as pd
import numpy as np
 
#importing and appending similar rows to of the dataframe
df = pd.read_csv('IMDB-Movie-Data.csv')
df1 = df.append(df.iloc[20:30,:])
 
#dropping the duplicates
df1 = df1.drop_duplicates()
 
#checking the duplicates
df1.duplicated().sum()

この方法が適用される列は、カテゴリ変数ではなく、数値変数でなければなりません。

分数の使用

この方法では、系列内の0.01分位未満、0.99分位以上の値がフィルタリングされます。

Missing Values Using Heatmap
Missing Values Using Heatmap

3. 重複したエントリの処理

DataFrameの重複をチェックするには、 .duplicated() メソッドを使用します。

これは、DataFrameではなく、PandasのSeriesを返します。

特定の列の重複をチェックするには、.duplicated( )メソッドの入力引数として列名を指定することができます。

これを実際に見てみましょう。

幸いなことに、私たちのデータフレームには重複する値がないので、データフレーム自体からいくつかの値を追加して、重複する値を作成します。

Finding Sum Of Missing Values
Finding Sum Of Missing Values
Output:
10

ここで、 .drop_duplicates() メソッドを使用して、データフレームから重複する値を削除します。

Before And After Filling Null Values
Before And After Filling Null Values
output:
0

おわりに

この記事は、Pandasを使用して、乱雑なデータセットに対して実行する必要がある基本的なデータクリーニング操作について学習するためのものでした。

それでは、よい学習を

タイトルとURLをコピーしました