Pythonでのデータクレンジング手法: 20の実践的テクニック

## はじめに

こんにちは！今回は、Pythonを使ったデータクレンジングの手法について、20の章に分けて詳しく解説していきます。データ分析や機械学習の前処理として欠かせないデータクレンジング。ぜひ、この記事を参考に、より効率的なデータ処理を目指しましょう！

まず、この記事全体で使用するサンプルデータを以下に示します。

```python
import pandas as pd
import numpy as np

# サンプルデータの作成
data = {
    'ID': [1, 2, 3, 4, 5],
    '名前': ['山田太郎', '佐藤花子', '鈴木一郎', '田中美咲', '高橋健太'],
    '年齢': [28, 35, np.nan, 42, 31],
    '性別': ['男', '女', '男', '女', '男'],
    '売上': [100000, 150000, 120000, np.nan, 200000],
    '部門': ['営業', '管理', '営業', '企画', '営業'],
    '入社日': ['2020-04-01', '2018/07/15', '2019-09-30', '2017-12-25', '2021-01-10']
}

df = pd.DataFrame(data)
print(df)
```

このサンプルデータを使用して、以下の20の手法を説明していきます。

## 1. 欠損値の処理

データセットには欠損値がつきものです。これらを適切に処理することが重要です。

```python
# 欠損値を0で埋める
df_filled = df.fillna(0)

# 欠損値を含む行を削除
df_dropped = df.dropna()

print("0で埋めた結果:")
print(df_filled)
print("\n欠損値を含む行を削除した結果:")
print(df_dropped)
```

## 2. 重複データの削除

重複したデータは分析結果に悪影響を与える可能性があります。

```python
# 重複行の追加（サンプル用）
df = df.append(df.iloc[0])

# 重複行の削除
df_unique = df.drop_duplicates()

print("重複削除後:")
print(df_unique)
```

## 3. データ型の変換

適切なデータ型に変換することで、処理速度の向上や正確な分析が可能になります。

```python
# 年齢と売上を数値型に変換
df['年齢'] = pd.to_numeric(df['年齢'], errors='coerce')
df['売上'] = pd.to_numeric(df['売上'], errors='coerce')

print(df.dtypes)
```

## 4. 外れ値の検出と処理

外れ値は分析結果を歪める可能性があるため、適切に処理する必要があります。

```python
import matplotlib.pyplot as plt

# 売上の箱ひげ図
plt.figure(figsize=(10, 6))
plt.boxplot(df['売上'].dropna())
plt.title('売上の箱ひげ図')
plt.show()

# IQRを使用して外れ値を検出
Q1 = df['売上'].quantile(0.25)
Q3 = df['売上'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

outliers = df[(df['売上'] < lower_bound) | (df['売上'] > upper_bound)]
print("外れ値:", outliers)
```

## 5. 文字列の正規化

文字列データを一貫した形式に変換することで、分析の精度が向上します。

```python
# 名前の正規化（姓と名を分離）
df[['姓', '名']] = df['名前'].str.extract('(.+)(.{1})')

print(df[['姓', '名']])
```

## 6. 日付データの処理

日付データは適切なフォーマットに変換することが重要です。

```python
# 日付形式の統一
df['入社日'] = pd.to_datetime(df['入社日'], format='mixed')

# 年、月、日の抽出
df['入社年'] = df['入社日'].dt.year
df['入社月'] = df['入社日'].dt.month
df['入社日'] = df['入社日'].dt.day

print(df[['入社年', '入社月', '入社日']])
```

## 7. カテゴリカルデータのエンコーディング

カテゴリカルデータを数値に変換することで、機械学習モデルで使用できるようになります。

```python
from sklearn.preprocessing import LabelEncoder

# 性別のエンコーディング
le = LabelEncoder()
df['性別_encoded'] = le.fit_transform(df['性別'])

print(df[['性別', '性別_encoded']])
```

## 8. スケーリング

特徴量のスケールを統一することで、機械学習モデルの性能が向上することがあります。

```python
from sklearn.preprocessing import StandardScaler

# 年齢と売上のスケーリング
scaler = StandardScaler()
df[['年齢_scaled', '売上_scaled']] = scaler.fit_transform(df[['年齢', '売上']].dropna())

print(df[['年齢', '年齢_scaled', '売上', '売上_scaled']])
```

## 9. 列名の変更

わかりやすい列名に変更することで、データの理解が容易になります。

```python
# 列名の変更
df = df.rename(columns={'ID': '従業員ID', '売上': '月間売上'})

print(df.columns)
```

## 10. データの結合

複数のデータセットを結合することで、より豊富な情報を得ることができます。

```python
# 新しいデータフレームの作成（サンプル用）
df_additional = pd.DataFrame({
    '従業員ID': [1, 2, 3, 4, 5],
    '評価': ['A', 'B', 'A', 'C', 'B']
})

# データの結合
df_merged = pd.merge(df, df_additional, on='従業員ID', how='left')

print(df_merged)
```

## 11. 列の削除

不要な列を削除することで、データセットをシンプルに保つことができます。

```python
# 不要な列の削除
df_dropped = df.drop(['姓', '名'], axis=1)

print(df_dropped.columns)
```

## 12. 文字列の分割

複合的な情報を含む文字列を分割することで、より詳細な分析が可能になります。

```python
# 部門を大分類と小分類に分割（サンプル用にデータを追加）
df['部門'] = df['部門'].replace('営業', '営業/国内')

df[['部門_大分類', '部門_小分類']] = df['部門'].str.split('/', expand=True)

print(df[['部門', '部門_大分類', '部門_小分類']])
```

## 13. 条件付きデータ処理

条件に基づいてデータを処理することで、より柔軟なデータクレンジングが可能になります。

```python
# 年齢に基づいて世代を分類
df['世代'] = pd.cut(df['年齢'], bins=[0, 30, 40, 50, 100], labels=['20代', '30代', '40代', '50代以上'])

print(df[['年齢', '世代']])
```

## 14. 時系列データのリサンプリング

時系列データを適切な間隔でリサンプリングすることで、トレンドの把握が容易になります。

```python
# 日次の売上データを作成（サンプル用）
dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='D')
daily_sales = pd.DataFrame({'日付': dates, '日次売上': np.random.randint(1000, 5000, size=len(dates))})
daily_sales.set_index('日付', inplace=True)

# 月次データへのリサンプリング
monthly_sales = daily_sales.resample('M').sum()

print(monthly_sales.head())
```

## 15. データの正規化

データを0から1の範囲に正規化することで、異なるスケールの特徴量を比較しやすくなります。

```python
from sklearn.preprocessing import MinMaxScaler

# 年齢と売上の正規化
scaler = MinMaxScaler()
df[['年齢_normalized', '月間売上_normalized']] = scaler.fit_transform(df[['年齢', '月間売上']].dropna())

print(df[['年齢', '年齢_normalized', '月間売上', '月間売上_normalized']])
```

## 16. テキストデータのクリーニング

テキストデータから不要な情報を除去し、分析に適した形に整えます。

```python
import re

# サンプルテキストデータの追加
df['コメント'] = ['良い (笑)', 'まあまあです。', 'もっと頑張れ！', '素晴らしい!!!', 'OK...']

# テキストクリーニング関数
def clean_text(text):
    text = re.sub(r'[^\w\s]', '', text)  # 特殊文字の削除
    text = text.lower()  # 小文字化
    return text.strip()  # 前後の空白を削除

df['クリーニング後コメント'] = df['コメント'].apply(clean_text)

print(df[['コメント', 'クリーニング後コメント']])
```

## 17. 欠損値の補完

平均値や中央値などで欠損値を補完することで、データの損失を最小限に抑えることができます。

```python
# 年齢の欠損値を平均値で補完
df['年齢_平均補完'] = df['年齢'].fillna(df['年齢'].mean())

# 売上の欠損値を中央値で補完
df['月間売上_中央値補完'] = df['月間売上'].fillna(df['月間売上'].median())

print(df[['年齢', '年齢_平均補完', '月間売上', '月間売上_中央値補完']])
```

## 18. データの集約

データを集約することで、全体的な傾向を把握しやすくなります。

```python
# 部門ごとの集約
df_agg = df.groupby('部門').agg({
    '年齢': ['mean', 'min', 'max'],
    '月間売上': ['sum', 'mean']
})

print(df_agg)
```

## 19. データの可視化

データを可視化することで、異常値や傾向を視覚的に確認できます。

```python
import matplotlib.pyplot as plt

# 部門ごとの平均売上
plt.figure(figsize=(10, 6))
df.groupby('部門')['月間売上'].mean().plot(kind='bar')
plt.title('部門ごとの平均売上')
plt.xlabel('部門')
plt.ylabel('平均売上')
plt.xticks(rotation=0)
plt.tight_layout()
plt.show()
```

## 20. データの保存

クレンジング後のデータを適切な形式で保存することで、後続の分析作業が容易になります。

```python
# CSVファイルとして保存
df.to_csv('cleaned_data.csv', index=False)

# Excelファイルとして保存
df.to_excel('cleaned_data.xlsx', index=False)

print("データを保存しました。")
```

以上、Pythonを使ったデータクレンジングの20の手法について解説しました。これらの技術を組み合わせることで、より効果的なデータ前処理が可能になります。データの特性や分析の目的に応じて、適切な手法を選択してください。

データクレンジングは地道な作業ですが、分析結果の質を大きく左右する重要なステップです。ぜひ、これらの手法を実践して、より質の高いデータ分析を目指してください！

最後に、クレンジング後のデータの一部を確認してみましょう。

```python
print(df.head())
```

このように、様々な手法を適用することで、元のデータがより分析しやすい形に整理されました。データクレンジングの重要性と、Pythonを使った効果的な手法について理解を深めていただけたでしょうか。

データサイエンスの世界では、クリーンで整理されたデータは金と同じくらい価値があります。これらの技術を磨き、データから価値ある洞察を引き出す力を身につけていきましょう！