Pandas データクリーニング

データクリーニングとは、不要なデータを処理するプロセスです。

多くのデータセットには、データの欠損、データ形式のエラー、エラーデータ、重複データなどが存在します。データ分析をより正確にするには、これらの不要なデータを処理する必要があります。

データクリーニングと前処理の一般的な手順:

  1. 欠損値の処理:欠損値を特定して補完するか、欠損値を含む行/列を削除します。

  2. 重複データの処理:重複データをチェックして削除し、各データが一意であることを確認します。

  3. 異常値の処理:極端な値や誤った値などの異常値を特定して処理します。

  4. データ形式の変換:データ型の変換や単位変換(例:日付形式の変換)を行います。

  5. 標準化と正規化:数値データを標準化(例:Z-score)または正規化(例:Min-Max)します。

  6. カテゴリデータのエンコーディング:カテゴリ変数を数値形式に変換します。一般的な方法には、One-Hot エンコーディングやラベルエンコーディングがあります。

  7. テキスト処理:テキストデータをクリーニングします。ストップワードの除去、ステミング、トークン化などを行います。

  8. データサンプリング:データセットからサンプルを抽出するか、オーバーサンプリング/アンダーサンプリングによってクラスの不均衡を処理します。

  9. 特徴量エンジニアリング:新しい特徴量を作成したり、無関係な特徴量を削除したり、重要な特徴量を選択したりします。

このチュートリアルでは、Pandas パッケージを使用してデータクリーニングを行います。

この記事で使用するテストデータproperty-data.csvは次のとおりです:

上の表には、4種類の欠損データが含まれています:

  • n/a
  • NA
  • —
  • na

Pandas で欠損値をクリーニングする

欠損値を含む行を削除する場合は、dropna()メソッドを使用できます。構文は次のとおりです:

DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

パラメータの説明:

  • axis:デフォルトは0、欠損値があると行全体を削除します。パラメータをaxis=1に設定すると、欠損値があると列全体を削除します。
  • how:デフォルトは'any'、行(または列)内のいずれかのデータに NA が出現すると行全体を削除します。設定する場合how='all'、行(または列)がすべて NA の場合のみ行全体を削除します。
  • thresh:保持するために必要な非欠損値の数を設定します。
  • subset:確認したい列を設定します。複数の列の場合は、列名のリストをパラメータとして使用できます。
  • inplace:True に設定すると、計算された値を以前の値に直接上書きして None を返し、ソースデータを変更します。

我々はisnull()各セルが空かどうかを判断できます。

例

import pandas as pd

df = pd.read_csv('property-data.csv')

print (df['NUM_BEDROOMS'])
print (df['NUM_BEDROOMS'].isnull())

上記の例の出力結果は次のとおりです:

上記の例では、Pandas が n/a と NA を欠損データとして扱い、na は欠損データではないため、要件を満たしていません。欠損データの型を指定できます:

例

import pandas as pd

missing_values = ["n/a", "na", "--"]
df = pd.read_csv('property-data.csv', na_values = missing_values)

print (df['NUM_BEDROOMS'])
print (df['NUM_BEDROOMS'].isnull())

上記の例の出力結果は次のとおりです:

次の例では、欠損データを含む行を削除する方法を示します。

例

import pandas as pd

df = pd.read_csv('property-data.csv')

new_df = df.dropna()

print(new_df.to_string())

上記の例の出力結果は次のとおりです:

注意:デフォルトでは、dropna() メソッドは新しい DataFrame を返し、ソースデータを変更しません。

ソースデータの DataFrame を変更する場合は、inplace = Trueパラメータを使用できます:

例

import pandas as pd

df = pd.read_csv('property-data.csv')

df.dropna(inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです:

指定した列に欠損値がある行を削除することもできます:

例

ST_NUM 列のフィールド値が空の行を削除します:

import pandas as pd

df = pd.read_csv('property-data.csv')

df.dropna(subset=['ST_NUM'], inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです:

我々はまたfillna()メソッドを使用していくつかの空フィールドを置き換えることができます:

例

12345 を使用して空フィールドを置き換えます:

import pandas as pd

df = pd.read_csv('property-data.csv')

df.fillna(12345, inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです:

特定の列を指定してデータを置き換えることもできます:

例

12345 を使用して PID の欠損データを置き換えます:

import pandas as pd

df = pd.read_csv('property-data.csv')

df['PID'].fillna(12345, inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです:

空のセルを置き換える一般的な方法は、列の平均値、中央値、または最頻値を計算することです。

Pandas はmean()、median()とmode()メソッドで列の平均値(すべての値を合計した平均)、中央値(並べ替えた後に中央に位置する値)、最頻値(最も頻繁に出現する値)を計算します。

例

mean() メソッドを使用して列の平均値を計算し、空のセルを置き換えます:

import pandas as pd

df = pd.read_csv('property-data.csv')

x = df["ST_NUM"].mean()

df["ST_NUM"].fillna(x, inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです。赤枠が計算された平均値で置き換えられた空のセルです:

例

median() メソッドを使用して列の中央値を計算し、空のセルを置き換えます:

import pandas as pd

df = pd.read_csv('property-data.csv')

x = df["ST_NUM"].median()

df["ST_NUM"].fillna(x, inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです。赤枠が計算された中央値で置き換えられた空のセルです:

例

mode() メソッドを使用して列の最頻値を計算し、空のセルを置き換えます:

import pandas as pd

df = pd.read_csv('property-data.csv')

x = df["ST_NUM"].mode()

df["ST_NUM"].fillna(x, inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです。赤枠が計算された最頻値で置き換えられた空のセルです:


Pandas で形式エラーのデータをクリーニングする

データ形式が誤っているセルは、データ分析を困難にし、場合によっては不可能にします。

空のセルを含む行を処理するか、列内のすべてのセルを同じ形式のデータに変換することで対応できます。

次の例では日付をフォーマットします:

例

import pandas as pd

# 3番目の日付は形式が正しくありません
data = {
  "Date": ['2020/12/01', '2020/12/02' , '20201226'],
  "duration": [50, 40, 45]
}

df = pd.DataFrame(data, index = ["day1", "day2", "day3"])

df['Date'] = pd.to_datetime(df['Date'], format='mixed')

print(df.to_string())

上記の例の出力結果は次のとおりです:

           Date  duration
day1 2020-12-01        50
day2 2020-12-02        40
day3 2020-12-26        45

Pandas でエラーデータをクリーニングする

データエラーも非常に一般的なケースです。エラーデータを置き換えたり削除したりできます。

次の例では、誤った年齢データを置き換えます:

例

import pandas as pd

person = {
  "name": ['Google', 'サンプル' , 'Taobao'],
  "age": [50, 40, 12345]    # 12345 の年齢データは誤りです
}

df = pd.DataFrame(person)

df.loc[2, 'age'] = 30 # データを修正する

print(df.to_string())

上記の例の出力結果は次のとおりです:

     name  age
0  Google   50
1  サンプル   40
2  Taobao   30

条件文を設定することもできます:

例

age が 120 より大きいものを 120 に設定します:

import pandas as pd

person = {
  "name": ['Google', 'サンプル' , 'Taobao'],
  "age": [50, 200, 12345]    
}

df = pd.DataFrame(person)

for x in df.index:
  if df.loc[x, "age"] > 120:
    df.loc[x, "age"] = 120

print(df.to_string())

上記の例の出力結果は次のとおりです:

     name  age
0  Google   50
1  サンプル  120
2  Taobao  120

エラーデータの行を削除することもできます:

例

age が 120 より大きいものを削除します:

import pandas as pd

person = {
  "name": ['Google', 'サンプル' , 'Taobao'],
  "age": [50, 40, 12345]    # 12345 の年齢データは誤りです
}

df = pd.DataFrame(person)

for x in df.index:
  if df.loc[x, "age"] > 120:
    df.drop(x, inplace = True)

print(df.to_string())

上記の例の出力結果は次のとおりです:

     name  age
0  Google   50
1  サンプル   40

Pandas で重複データをクリーニングする

重複データをクリーニングしたい場合は、duplicated()とdrop_duplicates()メソッドを使用できます。

対応するデータが重複している場合、duplicated()True が返され、それ以外の場合は False が返されます。

例

import pandas as pd

person = {
  "name": ['Google', 'サンプル', 'サンプル', 'Taobao'],
  "age": [50, 40, 40, 23]  
}
df = pd.DataFrame(person)

print(df.duplicated())

上記の例の出力結果は次のとおりです:

0    False
1    False
2     True
3    False
dtype: bool

重複データを削除するには、drop_duplicates()メソッドを直接使用できます。

例

import pandas as pd

persons = {
  "name": ['Google', 'サンプル', 'サンプル', 'Taobao'],
  "age": [50, 40, 40, 23]  
}

df = pd.DataFrame(persons)

df.drop_duplicates(inplace = True)
print(df)

上記の例の出力結果は次のとおりです:

     name  age
0  Google   50
1  サンプル   40
3  Taobao   23

よく使うメソッドと説明

データクリーニングと前処理の一般的な方法:

操作方法/手順説明よく使う関数/メソッド
欠損値の処理欠損値の補完指定された値(例:平均値、中央値、最頻値など)を使用して欠損値を補完します。df.fillna(value)
欠損値の削除欠損値を含む行または列を削除します。df.dropna()
重複データの処理重複データの削除DataFrame 内の重複行を削除します。df.drop_duplicates()
異常値の処理異常値の検出(統計的手法に基づく)Z-score または IQR 法を使用して異常値を特定し処理します。カスタム関数(例:Z-score または IQR に基づく)
異常値の置き換え適切な値(例:平均値または中央値)を使用して異常値を置き換えます。カスタム関数(例:異常値の置き換え)
データ形式の変換データ型の変換データ型をある型から別の型に変換します。例:文字列を日付に変換します。df.astype()
日時形式の変換文字列または数値を日時型に変換します。pd.to_datetime()
標準化と正規化標準化データを平均0、標準偏差1の分布に変換します。StandardScaler()
正規化データを指定された範囲(例: [0, 1])にスケーリングします。MinMaxScaler()
カテゴリデータのエンコーディングラベルエンコーディングカテゴリ変数を整数形式に変換します。LabelEncoder()
ワンホットエンコーディング(One-Hot Encoding)各カテゴリを新しいバイナリ特徴量に変換します。pd.get_dummies()
テキストデータ処理ストップワードの除去テキストから重要でない単語("the"、"is" など)を除去します。カスタム関数(基づくnltk 或 spaCy)
ステミングと見出し語化(レンマ化)語幹を抽出するか、単語の基本形を復元します。nltk.stem.PorterStemmer()
トークン化(分かち書き)テキストを単語または部分語(サブワード)に分割します。nltk.word_tokenize()
データサンプリングランダムサンプリングデータから一定割合のサンプルをランダムに抽出します。df.sample()
オーバーサンプリングとアンダーサンプリングオーバーサンプリング(少数クラスのサンプルを複製)またはアンダーサンプリング(多数クラスのサンプルを削減)によって、データセット内のクラス分布を均衡させます。SMOTE()(オーバーサンプリング);RandomUnderSampler()(アンダーサンプリング)
特徴量エンジニアリング特徴量選択ターゲット変数に影響を与える特徴量を選択し、冗長または無関係な特徴量を除去します。SelectKBest()
特徴量抽出元のデータから新しい特徴量を作成し、モデルの予測能力を向上させます。PolynomialFeatures()
特徴量スケーリング数値特徴量を同じ桁数(スケール)になるようスケーリングします。MinMaxScaler() 、 StandardScaler()
カテゴリ特徴量のマッピング特徴量マッピングカテゴリ変数を対応する数値エンコーディングにマッピングします。カスタムマッピング関数
データの結合と連結データのマージ複数のDataFrameを特定の列に基づいてマージします。内部結合、外部結合、左結合、右結合などに対応しています。pd.merge()
データの連結複数のDataFrameを行または列方向に連結します。pd.concat()
データの再形成(リシェイプ)ピボットテーブルデータを特定の次元に基づいてグループ化し、集計結果を計算します。pd.pivot_table()
データ変形データの形状を変更します。例えば、ロング形式からワイド形式へ、またはワイド形式からロング形式へ変換します。df.melt() 、 df.pivot()
データ型の変換と処理文字列処理文字列データを処理します。スペースの除去、大文字小文字の変換などを行います。str.replace() 、 str.upper() 等
グループ集計特定の特徴量に基づいてグループ化した後に集計計算を行います。df.groupby()
欠損値の予測補完モデルを使用して欠損値を予測して補完機械学習モデル(例: 回帰モデル)を使用して欠損値を予測し、欠損データを補完します。カスタムモデル(例:sklearn.linear_model.LinearRegression)
時系列処理時系列の欠損値補完時系列の手法(前方補完、後方補完など)を使用して欠損値を補完します。df.fillna(method='ffill')
ローリングウィンドウ計算スライディングウィンドウを使用して時系列データの統計計算(例: 平均、標準偏差など)を行います。df.rolling(window=5).mean()
データ変換とマッピングデータのマッピングと置換データ内の特定の値を他の値に置換します。df.replace()

欠損値の補完:

例

import pandas as pd

# サンプルデータ
data = {'Name': ['Alice', 'Bob', 'Charlie', None],
        'Age': [25, 30, None, 35],
        'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']}

df = pd.DataFrame(data)

# 欠損している "Age" を平均値で補完
df['Age'].fillna(df['Age'].mean(), inplace=True)

print(df)

出力:

      Name  Age           City
0    Alice   25.0       New York
1      Bob   30.0    Los Angeles
2  Charlie   30.0        Chicago
3     None   35.0        Houston

ワンホットエンコーディング:

例

import pandas as pd

# サンプルデータ
data = {'City': ['New York', 'Los Angeles', 'Chicago', 'Houston']}

df = pd.DataFrame(data)

# "City" 列に対して One-Hot エンコーディングを実行
df_encoded = pd.get_dummies(df, columns=['City'])

print(df_encoded)

出力:

   City_Chicago  City_Houston  City_Los Angeles  City_New York
0             0             0                 0              1
1             0             0                 1              0
2             1             0                 0              0
3             0             1                 0              0

標準化:

例

from sklearn.preprocessing import StandardScaler
import pandas as pd

# サンプルデータ
data = {'Age': [25, 30, 35, 40, 45],
        'Salary': [50000, 60000, 70000, 80000, 90000]}

df = pd.DataFrame(data)

# データを標準化
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df)

print(df_scaled)

出力:

[[-1.41421356 -1.41421356]
 [-0.70710678 -0.70710678]
 [ 0.          0.        ]
 [ 0.70710678  0.70710678]
 [ 1.41421356  1.41421356]]
その他の拡張