Pandas データ結合と欠損値処理

merge/concatの結合と、isna/fillna/dropnaの欠損値処理。実データ前処理の必須スキル。

複数表の結合と欠損値の処理。実データ分析で必ず必要になる前処理スキル。

白峰 リリ(普段) 白峰 リリ

複数のCSVを組み合わせるのって、SQLのJOINみたいなことPandasでもできるの?

神楽 モニカ 先生(笑顔) 神楽 モニカ 先生

もちろんできるわよ。 pd.mergeとpd.concatが代表ね。

import pandas as pd

customers = pd.DataFrame({
    'customer_id': [1, 2, 3, 4],
    'name': ['Alice', 'Bob', 'Charlie', 'David'],
})
orders = pd.DataFrame({
    'order_id': [101, 102, 103, 104, 105],
    'customer_id': [1, 2, 1, 3, 5],   # 5は customers に存在しない
    'amount': [3000, 5000, 2000, 8000, 1500],
})

# (1) merge: SQLのJOINに相当
inner = pd.merge(customers, orders, on='customer_id', how='inner')
left = pd.merge(customers, orders, on='customer_id', how='left')
outer = pd.merge(customers, orders, on='customer_id', how='outer')

# (2) concat: 縦/横方向の結合
df1 = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
df2 = pd.DataFrame({'a': [5, 6], 'b': [7, 8]})
stacked = pd.concat([df1, df2], axis=0, ignore_index=True)  # 縦結合
紅林 かえで(普段) 紅林 かえで

つまりpd.mergeはSQLのJOIN相当で、how='inner/left/right/outer'で種類を選ぶ。 pd.concatは単純に縦か横にスタックする、という理解で合っていますか?

白峰 リリ(普段) 白峰 リリ

欠損値ってどうやって扱えばいいの?

import numpy as np

# 欠損値検出
df.isna().sum()              # 列ごとの欠損数
df.isna().any(axis=1)         # 各行に欠損があるか

# 欠損値処理
df_dropped = df.dropna()                    # 欠損行を削除
df_filled  = df.fillna(0)                   # 0で埋める
df_filled  = df.fillna(df.mean())           # 列ごとの平均で埋める
df_filled  = df.fillna(method='ffill')      # 前の値で埋める(時系列向け)

# 列ごとに違う埋め方
df['age'] = df['age'].fillna(df['age'].median())
df['gender'] = df['gender'].fillna('不明')
藍沢 しずく(普段) 藍沢 しずく

欠損値って、どれで埋めるか難しいですぅ…

神楽 モニカ 先生(普段) 神楽 モニカ 先生

数値列なら平均か中央値、カテゴリ列なら最頻値や『不明』、時系列なら前後の値を使う、というのが定石ね。 大事なのは『何で埋めたかをきちんとドキュメント化する』ということね。

紅林 かえで(普段) 紅林 かえで

補足すると、単純な平均埋めには注意が必要。 列の平均で全行を埋めるとデータの分散が下がってしまって、その後の分析にバイアスが入る。 多重代入法みたいな高度な手法もある。

白峰 リリ(普段) 白峰 リリ

どれくらい欠損があったら、もう諦めて行ごと削除しちゃう?

神楽 モニカ 先生(普段) 神楽 モニカ 先生

目安として『1行に欠損が大半ある』『列の50%以上が欠損』なら削除を検討。 ただしデータ量が少ない場合は埋めることも検討。 ケースバイケース。

紅林 かえで(普段) 紅林 かえで

DS検定★では merge の how の違い、isna/fillna/dropna の使い分けが頻出。

確認クイズ

pd.merge(df1, df2, on='id', how='left') の結果として正しいのはどれか。

  1. 両方に存在する id のみが結果に残る
  2. df1 の全行が結果に残り、df2 にない場合は NaN になる
  3. df2 の全行が結果に残る
  4. 両方の和集合(両方にあれば残る)
こたえを見る

正解: 2. df1 の全行が結果に残り、df2 にない場合は NaN になる

df1 の全行が結果に残り、df2 にない場合は NaN になる。 how='left' は SQL の LEFT JOIN 相当で、左側(df1)の全行を保持し、右側にマッチしない場合は欠損値で埋められます。

🔖 この記事の関連書籍

Amazonアソシエイトリンクを含みます。他分野は おすすめ書籍ページ へ。