(学習ログ)Python022:pandasで複数のマスターデータを結合する方法
1. はじめに
この記事では、pandasのmerge()を使って複数のマスターデータを順次結合する方法を学びます。
実務でよくある「顧客マスター」「クラスマスター」「キャンペーンマスター」などを利用ログと結びつけるパターンを例に、データ結合の基本から結合後の確認方法までを解説します。結合の仕組みを理解すれば、データ分析の幅が一気に広がります。
2. サンプルコード
コード全文
import pandas as pd
# 利用ログデータを読み込む
sample_usagelog = pd.read_csv('003_サンプル/usage_log.csv')
# 顧客マスターを読み込む
sample_customer = pd.read_csv('003_サンプル/customer_master.csv')
# クラスマスターを読み込む
sample_class_master = pd.read_csv('003_サンプル/class_master.csv')
# キャンペーンマスターを読み込む
sample_campaign_master = pd.read_csv('003_サンプル/campaign_master.csv')
# 顧客マスターとクラスマスターを結合(class列をキーに)
sample_customer_join = pd.merge(sample_customer, sample_class_master, on="class", how="left")
# さらにキャンペーンマスターを結合(campaign_id列をキーに)
sample_customer_join = pd.merge(sample_customer_join, sample_campaign_master, on="campaign_id", how="left")
# 結合後のデータの先頭5行を表示
sample_customer_join.head()
# 元の顧客マスターの行数を確認
print(len(sample_customer))
# 結合後のデータの行数を確認
print(len(sample_customer_join))
# 欠損値の数を列ごとに確認
sample_customer_join.isnull().sum()
コード解説
■ データの読み込み(1〜8行目)
4つのCSVファイルを読み込んでいます。
それぞれの役割は
-
usage_log.csv:利用ログ(今回は未使用) -
customer_master.csv:顧客の基本情報 -
class_master.csv:顧客クラス(ランク)の詳細情報 -
campaign_master.csv:キャンペーンの詳細情報
なぜ複数のファイルに分けるのか?
データベース設計の基本で、情報を正規化することで更新の手間を減らし、データの一貫性を保ちます。例えば、クラス名を変更したい場合、1つのマスターファイルだけ修正すればOKです。
■ 1回目の結合:顧客×クラス(10行目)
sample_customer_join = pd.merge(sample_customer, sample_class_master, on="class", how="left")
pd.merge()の引数:
- 第1引数:左側のデータフレーム(ここでは顧客マスター)
- 第2引数:右側のデータフレーム(ここではクラスマスター)
-
on="class":結合のキーとなる列名 -
how="left":左外部結合(左側のデータは全て残す)
初心者がつまずきやすいポイント:
how="left"は「左側のデータを優先する」という意味です。右側にマッチするデータがなくても、左側の行は残ります(該当列はNaNになる)。
■ 2回目の結合:結果×キャンペーン(13行目)
sample_customer_join = pd.merge(sample_customer_join, sample_campaign_master, on="campaign_id", how="left")
1回目の結合結果に、さらにキャンペーンマスターを結合します。このように、merge()を連続して使うことで3つ以上のデータを結合できます。
■ データの確認(16〜22行目)
結合後は必ず確認が必要です:
-
.head():先頭5行を目視確認 -
len():行数の変化をチェック(意図しない増減がないか) -
.isnull().sum():欠損値の発生を確認
実行結果例
# 結合前の顧客マスター行数
1000
# 結合後の行数
1000
# 欠損値の確認結果
customer_id 0
customer_name 0
class 0
class_name 0
campaign_id 50
campaign_name 50
dtype: int64
結果の読み方:
- 行数が変わっていない → 1対1の結合に成功
-
campaign_idに50件の欠損 → 50人の顧客はキャンペーンに参加していない
3. エラーと確認のポイント
代表的なエラー
❌ KeyError: 'class'
KeyError: 'class'
原因: 結合キーとして指定した列名が、どちらか(または両方)のデータフレームに存在しない。
対処法:
# 列名を確認
print(sample_customer.columns)
print(sample_class_master.columns)
スペルミスや大文字小文字の違いがないかチェックしましょう。
❌ 行数が意図せず増える
print(len(sample_customer)) # 1000
print(len(sample_customer_join)) # 1500(増えてしまった!)
原因: 結合キーが重複していて、1対多の関係になっている。
対処法:
# キーの重複を確認
sample_class_master['class'].duplicated().sum()
❌ MergeError
MergeError: No common columns to perform merge on
原因: onパラメータを指定せず、かつ共通の列名がない。
対処法: 左右で列名が異なる場合はleft_onとright_onを使用:
pd.merge(df1, df2, left_on='id', right_on='customer_id', how='left')
よく使う確認メソッド
1. .info() - データ構造の概要確認
sample_customer_join.info()
出力例:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 customer_id 1000 non-null int64
1 customer_name 1000 non-null object
2 class 1000 non-null object
3 class_name 1000 non-null object
4 campaign_id 950 non-null float64
5 campaign_name 950 non-null object
データ型と欠損値の有無を一目で確認できます。
2. .duplicated() - 重複行のチェック
# 重複行の数を確認
sample_customer_join.duplicated().sum()
# 特定の列での重複確認
sample_customer_join.duplicated(subset=['customer_id']).sum()
出力例:
0 # 重複なし
3. .describe() - 数値列の統計情報
sample_customer_join.describe()
出力例:
customer_id campaign_id
count 1000.000000 950.000000
mean 500.500000 25.300000
std 288.819436 14.500000
min 1.000000 1.000000
max 1000.000000 50.000000
結合後の数値データの分布を確認し、異常値がないかチェックできます。
4. .value_counts() - カテゴリの分布確認
sample_customer_join['class'].value_counts()
出力例:
Gold 350
Silver 300
Bronze 250
Platinum 100
Name: class, dtype: int64
結合後のカテゴリバランスが想定通りか確認できます。
4. まとめ
-
pd.merge()を使った基本的なデータ結合方法:onとhowパラメータの使い方を習得できました - 複数テーブルの段階的な結合パターン:2回以上のmergeを連続して実行する実践的な手法を学びました
- 結合後の必須チェック項目:行数・欠損値・データ型の確認方法を理解できました
- 実務でよくあるエラーと対処法:KeyErrorや行数増加など、典型的なトラブルに対応できるようになりました
Discussion