【pandas徹底解説】merge関数の使い方を7つのユースケースで完全マスター!

pandasのmerge関数は、データ分析や機械学習のプロジェクトで欠かせないツールです。この記事では、merge関数の基本から実践的な使い方まで、7つのユースケースを通じて徹底的に解説します。初心者からデータ分析のプロまで、必見の内容となっています。

この記事を読んだらわかること
  • merge関数の基本的な使い方
  • 7つの実践的なユースケース
  • merge関数を使う上での注意点
  • パフォーマンス改善のヒント
  • pandasを使ったデータ分析のステップアップ方法

pandasのmerge関数とは?

データ分析や機械学習のプロジェクトでは、異なるデータソースから取得したデータを組み合わせる必要があることが少なくありません。pandasのmerge関数は、そのような場面で強力なツールとなります。merge関数を使えば、複数のデータフレームを簡単に結合できるのです。

merge関数を使うメリット

merge関数は、SQLのJOIN句に似た機能を提供しています。異なるデータフレームに共通のカラムがある場合、そのカラムを基準にデータを結合できます。また、内部結合や外部結合など、様々な結合方法を選択することもできます。

例えば、ユーザー情報とアクセスログが別々のデータフレームに格納されている場合を考えてみましょう。merge関数を使えば、ユーザーIDを基準に2つのデータフレームを結合し、ユーザー属性とアクセス履歴を1つのデータフレームにまとめることができます。

import pandas as pd

# ユーザー情報のデータフレーム
users = pd.DataFrame({'user_id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Carol'], 'age': [25, 30, 35]})

# アクセスログのデータフレーム
logs = pd.DataFrame({'user_id': [1, 1, 2, 3], 'date': ['2023-01-01', '2023-01-02', '2023-01-01', '2023-01-03'], 'page': ['home', 'settings', 'home', 'about']})

# user_idを基準に内部結合
merged_df = pd.merge(users, logs, on='user_id')
print(merged_df)

出力結果:

   user_id   name  age        date      page
0        1  Alice   25  2023-01-01      home
1        1  Alice   25  2023-01-02  settings
2        2    Bob   30  2023-01-01      home
3        3  Carol   35  2023-01-03     about

このように、merge関数を使うことで、データの前処理やクリーニングが容易になります。特に、SQLのJOIN操作に慣れている人にとっては、直感的に使いやすい関数だと言えるでしょう。

次の見出しでは、merge関数の基本的な使い方について、詳しく解説していきます。

merge関数の基本的な使い方

pandasのmerge関数は、複数のデータフレームを結合するための強力なツールです。基本的な使い方を理解することで、データ分析や機械学習のプロジェクトで効果的に活用することができるでしょう。

merge関数の書式と引数の説明

merge関数の基本的な書式は以下の通りです。

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

主要な引数の意味は次のようになります。

  • left, right: 結合するデータフレーム
  • how: 結合方法を指定します。’inner’(内部結合)、’outer’(外部結合)、’left’(左結合)、’right’(右結合)から選択できます。
  • on: 両方のデータフレームに共通するカラム名を指定します。このカラムを基準に結合が行われます。
  • left_on, right_on: データフレームごとに異なるカラム名を指定して結合する場合に使います。
  • left_index, right_index: インデックスを使って結合する場合にTrueに設定します。
  • suffixes: 結合後のデータフレームで、重複するカラム名に付加する接尾辞を指定します。

単純な結合の例

以下は、学生の情報と成績を結合する簡単な例です。

import pandas as pd

# 学生情報のデータフレーム
students = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Carol']})

# 成績情報のデータフレーム
grades = pd.DataFrame({'id': [1, 2, 4], 'math': [80, 90, 75], 'science': [85, 95, 80]})

# idを基準に内部結合
merged_df = pd.merge(students, grades, on='id', how='inner')
print(merged_df)

出力結果:

   id   name  math  science
0   1  Alice    80       85
1   2    Bob    90       95

この例では、studentsとgradesの2つのデータフレームを、共通のカラム’id’を基準に内部結合しています。結合後のデータフレームmerged_dfには、idが一致する行だけが含まれています。

merge関数の使い方を理解することで、様々なデータ結合のニーズに対応できるようになります。次の見出しでは、具体的なユースケースを7つ紹介し、merge関数の実践的な活用方法を探っていきます。

mergeのユースケース7選

pandasのmerge関数は、様々なデータ結合のニーズに対応できる強力なツールです。ここでは、データ分析や機械学習のプロジェクトでよく遭遇する7つのユースケースを紹介し、実践的なmerge関数の使い方を解説します。

1. 共通のカラムを指定して結合する

最も基本的なユースケースは、共通のカラムを指定して2つのデータフレームを結合することです。例えば、顧客情報と購入履歴を顧客IDで結合し、顧客ごとの購入履歴を分析する場合は以下のようにします。

import pandas as pd

# 顧客情報のデータフレーム
customers = pd.DataFrame({'customer_id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Carol'], 'age': [25, 30, 35]})

# 購入履歴のデータフレーム
purchases = pd.DataFrame({'customer_id': [1, 1, 2, 3], 'product': ['A', 'B', 'C', 'D'], 'price': [100, 200, 300, 400]})

# customer_idを基準に内部結合
merged_df = pd.merge(customers, purchases, on='customer_id', how='inner')
print(merged_df)

出力結果:

   customer_id   name  age product  price
0            1  Alice   25       A    100
1            1  Alice   25       B    200
2            2    Bob   30       C    300
3            3  Carol   35       D    400

この例では、customersとpurchasesの2つのデータフレームを、共通のカラム’customer_id’を基準に内部結合しています。結合後のデータフレームmerged_dfには、顧客情報と購入履歴が結合された状態で保存されます。

2. 結合するカラム名が異なる場合の対処法

結合するデータフレームのカラム名が異なる場合は、left_onとright_onを使って対応するカラムを指定します。例えば、社員情報と給与情報を結合する際、社員情報では’employee_id’、給与情報では’id’というカラム名を使用している場合は以下のようにします。

import pandas as pd

# 社員情報のデータフレーム
employees = pd.DataFrame({'employee_id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Carol'], 'department': ['Sales', 'Marketing', 'Engineering']})

# 給与情報のデータフレーム
salaries = pd.DataFrame({'id': [1, 2, 4], 'salary': [5000, 6000, 7000]})

# employee_idとidを基準に内部結合
merged_df = pd.merge(employees, salaries, left_on='employee_id', right_on='id', how='inner')
print(merged_df)

出力結果:

   employee_id   name department  id  salary
0            1  Alice      Sales   1    5000
1            2    Bob  Marketing   2    6000

この例では、left_on=’employee_id’とright_on=’id’を指定することで、カラム名が異なる場合でも正しく結合できています。

3. 片方のデータフレームにしかないデータの扱い方

片方のデータフレームにしかないデータを結合後も残したい場合は、howパラメータを’left’または’right’に設定します。例えば、ユーザー情報とアクセスログを結合する際、アクセスログにはないユーザーの情報を残す場合は以下のようにします。

import pandas as pd

# ユーザー情報のデータフレーム
users = pd.DataFrame({'user_id': [1, 2, 3, 4], 'name': ['Alice', 'Bob', 'Carol', 'David']})

# アクセスログのデータフレーム
logs = pd.DataFrame({'user_id': [1, 1, 2, 3], 'date': ['2023-01-01', '2023-01-02', '2023-01-01', '2023-01-03'], 'page': ['home', 'settings', 'home', 'about']})

# user_idを基準に左結合
merged_df = pd.merge(users, logs, on='user_id', how='left')
print(merged_df)

出力結果:

   user_id   name        date      page
0        1  Alice  2023-01-01      home
1        1  Alice  2023-01-02  settings
2        2    Bob  2023-01-01      home
3        3  Carol  2023-01-03     about
4        4  David         NaN       NaN

この例では、how=’left’を指定することで、ユーザー情報にはあるがアクセスログにはないユーザー(David)の情報も結合後のデータフレームに残っています。アクセスログに対応する情報がない場合は、NaNで埋められます。

4. 重複データの扱い方

複数のデータソースから収集した情報を結合する際、重複するレコードが存在する可能性があります。そのような場合は、結合後にdrop_duplicates()メソッドを使って重複を削除できます。

import pandas as pd

# 商品情報のデータフレーム1
products1 = pd.DataFrame({
    'product_id': [1, 2, 3, 4, 3],
    'name': ['Product A', 'Product B', 'Product C', 'Product D', 'Product C'],
    'price': [10.99, 15.99, 7.99, 12.99, 8.99]
})

# 商品情報のデータフレーム2
products2 = pd.DataFrame({
    'product_id': [3, 4, 5, 6, 3],
    'name': ['Product C', 'Product D', 'Product E', 'Product F', 'Product C'],
    'price': [7.99, 12.99, 9.99, 14.99, 9.49]
})

# 商品IDを基準に外部結合
merged_products = pd.merge(products1, products2, on='product_id', how='outer', suffixes=('_1', '_2'))
print("結合後のデータフレーム:")
print(merged_products)

# 重複を削除
merged_products_unique = merged_products.drop_duplicates(subset=['product_id'])
print("\n重複削除後のデータフレーム:")
print(merged_products_unique)

出力結果:

結合後のデータフレーム:
   product_id     name_1  price_1     name_2  price_2
0           1  Product A    10.99        NaN      NaN
1           2  Product B    15.99        NaN      NaN
2           3  Product C     7.99  Product C     7.99
3           3  Product C     7.99  Product C     9.49
4           3  Product C     8.99  Product C     7.99
5           3  Product C     8.99  Product C     9.49
6           4  Product D    12.99  Product D    12.99
7           5        NaN      NaN  Product E     9.99
8           6        NaN      NaN  Product F    14.99

重複削除後のデータフレーム:
   product_id     name_1  price_1     name_2  price_2
0           1  Product A    10.99        NaN      NaN
1           2  Product B    15.99        NaN      NaN
2           3  Product C     7.99  Product C     7.99
6           4  Product D    12.99  Product D    12.99
7           5        NaN      NaN  Product E     9.99
8           6        NaN      NaN  Product F    14.99

この例では、product_idが重複している商品情報を2つのデータフレームから外部結合しています。結合後のデータフレームには重複レコードが存在しますが、drop_duplicates(subset=[‘product_id’])を使うことで、product_idを基準に重複を削除しています。

5. 複数のカラムを指定した結合

複数のカラムを指定して結合することもできます。例えば、商品情報と在庫情報を結合する際、商品コードとサイズの2つのカラムを指定する場合は以下のようにします。

import pandas as pd

# 商品情報のデータフレーム
products = pd.DataFrame({'product_code': ['A001', 'A001', 'B001', 'B001'], 'size': ['S', 'M', 'S', 'M'], 'price': [1000, 1200, 2000, 2200]})

# 在庫情報のデータフレーム
inventory = pd.DataFrame({'product_code': ['A001', 'A001', 'B001', 'C001'], 'size': ['S', 'M', 'M', 'L'], 'stock': [10, 20, 15, 30]})

# product_codeとsizeを基準に内部結合
merged_df = pd.merge(products, inventory, on=['product_code', 'size'], how='inner')
print(merged_df)

出力結果:

  product_code size  price  stock
0         A001    S   1000     10
1         A001    M   1200     20
2         B001    M   2200     15

この例では、on=[‘product_code’, ‘size’]を指定することで、商品コードとサイズの2つのカラムを基準に内部結合しています。

6. インデックスを使った結合

時系列データなどでは、日付をインデックスに設定して結合することがあります。その場合は、left_indexとright_indexをTrueに設定します。

import pandas as pd

# 売上データのデータフレーム
sales = pd.DataFrame({'date': ['2023-01-01', '2023-01-02', '2023-01-03'], 'product': ['A', 'B', 'C'], 'revenue': [100, 200, 300]})
sales.set_index('date', inplace=True)

# 経費データのデータフレーム
expenses = pd.DataFrame({'date': ['2023-01-01', '2023-01-03', '2023-01-05'], 'category': ['Rent', 'Utilities', 'Salaries'], 'cost': [1000, 500, 2000]})
expenses.set_index('date', inplace=True)

# インデックス(date)を基準に外部結合
merged_df = pd.merge(sales, expenses, left_index=True, right_index=True, how='outer')
print(merged_df)

出力結果:

           product  revenue   category    cost
date                                          
2023-01-01       A    100.0       Rent  1000.0
2023-01-02       B    200.0        NaN     NaN
2023-01-03       C    300.0  Utilities   500.0
2023-01-05     NaN      NaN   Salaries  2000.0

この例では、left_index=True, right_index=Trueを指定することで、インデックス(date)を基準に外部結合しています。販売データと経費データを日付で結合し、販売と経費の両方が存在する日付、販売のみ存在する日付、経費のみ存在する日付が結合後のデータフレームに含まれています。

7. 結合後のデータ確認とクリーニング

結合後のデータには、欠損値や不整合が存在する可能性があります。そのため、結合後にデータの確認とクリーニングが必要です。

import pandas as pd

# 顧客情報のデータフレーム
customers = pd.DataFrame({'customer_id': [1, 2, 3, 4], 'name': ['Alice', 'Bob', 'Carol', 'David'], 'age': [25, 30, 35, None]})

# 購入履歴のデータフレーム
purchases = pd.DataFrame({'customer_id': [1, 2, 2, 3, 5], 'product': ['A', 'B', 'C', 'D', 'E'], 'price': [100, 200, 300, 400, 500]})

# customer_idを基準に左結合
merged_df = pd.merge(customers, purchases, on='customer_id', how='left')
print("結合後のデータフレーム:")
print(merged_df)

# 欠損値の確認とクリーニング
print("\n欠損値の数:")
print(merged_df.isnull().sum())

merged_df = merged_df.dropna(subset=['age'])
print("\nageの欠損値を削除後のデータフレーム:")
print(merged_df)

出力結果:

結合後のデータフレーム:
   customer_id   name   age product  price
0            1  Alice  25.0       A  100.0
1            2    Bob  30.0       B  200.0
2            2    Bob  30.0       C  300.0
3            3  Carol  35.0       D  400.0
4            4  David   NaN     NaN    NaN

欠損値の数:
customer_id    0
name           0
age            1
product        1
price          1
dtype: int64

ageの欠損値を削除後のデータフレーム:
   customer_id   name   age product  price
0            1  Alice  25.0       A  100.0
1            2    Bob  30.0       B  200.0
2            2    Bob  30.0       C  300.0
3            3  Carol  35.0       D  400.0

この例では、結合後のデータフレームにはageとproduct、priceに欠損値が存在しています。isnull().sum()で欠損値の数を確認した後、dropna(subset=[‘age’])を使ってageの欠損値を含む行を削除しています。

以上の7つのユースケースは、merge関数を使ったデータ結合の代表的な例です。これらのユースケースを理解し、適切に活用することで、データ分析や機械学習のプロジェクトにおいて、効果的にデータを結合し、分析やモデル構築に必要な情報を得ることができるでしょう。

merge関数は、SQLのJOINと同様の機能を提供しており、データベースの知識があれば理解しやすいツールです。一方で、pandasならではの柔軟性と使いやすさがあり、Pythonでのデータ処理に欠かせない機能となっています。

これらのユースケースを踏まえて、次の見出しでは、merge関数を使う上での注意点について説明します。

merge関数の注意点

merge関数は非常に便利なツールですが、使い方によってはエラーが発生したり、予期しない結果になったりすることがあります。ここでは、merge関数を使う上での注意点について説明します。

エラーが起こるケースと対処法

  • 結合するカラム名の指定ミス
    on、left_on、right_onを使ってカラム名を指定する際、存在しないカラム名を指定するとエラーが発生します。
import pandas as pd

df1 = pd.DataFrame({'id': [1, 2, 3], 'value': ['A', 'B', 'C']})
df2 = pd.DataFrame({'id_new': [1, 2, 3], 'value': [10, 20, 30]})

merged_df = pd.merge(df1, df2, on='id')

エラーメッセージ:

KeyError: 'id'

対処法は、正しいカラム名を指定することです。この例では、df2のカラム名はid_newなので、left_onとright_onを使って正しいカラム名を指定します。

merged_df = pd.merge(df1, df2, left_on='id', right_on='id_new')
print(merged_df)

出力結果:

   id value_x  id_new  value_y
0   1       A       1       10
1   2       B       2       20
2   3       C       3       30
  • 予期しない結合結果
    merge関数では、デフォルトでは内部結合(inner join)が使われます。外部結合(outer join)を使いたい場合は、howパラメータを明示的に指定する必要があります。
import pandas as pd

df1 = pd.DataFrame({'id': [1, 2, 3, 4], 'value': ['A', 'B', 'C', 'D']})
df2 = pd.DataFrame({'id': [1, 2, 5], 'value': [10, 20, 50]})

merged_df_inner = pd.merge(df1, df2, on='id')
print("内部結合の結果:")
print(merged_df_inner)

merged_df_outer = pd.merge(df1, df2, on='id', how='outer')
print("\n外部結合の結果:")
print(merged_df_outer)

出力結果:

内部結合の結果:
   id value_x  value_y
0   1       A       10
1   2       B       20

外部結合の結果:
   id value_x  value_y
0   1       A     10.0
1   2       B     20.0
2   3       C      NaN
3   4       D      NaN
4   5     NaN     50.0

内部結合では、両方のデータフレームに存在するidのみが結合されますが、外部結合では片方のデータフレームにしか存在しないidも結合後のデータフレームに含まれます。意図した結果を得るためには、howパラメータを適切に設定することが重要です。

パフォーマンスを意識した使い方

merge関数を使う際は、パフォーマンスにも配慮することが大切です。以下は、パフォーマンスを改善するためのヒントです。

  • 大きなデータフレームを結合する場合、mergeの前にdrop_duplicates()を使って重複を削除しておくと、パフォーマンスが向上する可能性があります。
  • 結合するカラムにindexを設定しておくことで、mergeのパフォーマンスが改善される場合があります。
  • 結合後に必要なカラムだけを選択することで、メモリ使用量を削減できます。

以上の注意点とパフォーマンス改善のヒントを理解し、適切に活用することで、merge関数をより効果的に使いこなすことができるでしょう。

まとめ

この記事では、pandasのmerge関数について、基本的な使い方からユースケース、注意点まで詳しく解説してきました。merge関数は、複数のデータフレームを結合するための強力なツールであり、データ分析や機械学習のプロジェクトで頻繁に使用されます。

merge関数の使いこなしポイント

merge関数を効果的に使いこなすためには、以下のポイントを押さえておくことが重要です。

  1. データ型の不一致によるエラーを避けるため、結合するカラムのデータ型を揃える。
  2. 結合するカラム名を正しく指定し、存在しないカラム名を指定しないようにする。
  3. 内部結合と外部結合の違いを理解し、目的に応じて適切な結合方法を選択する。
  4. パフォーマンスを意識し、大きなデータフレームを結合する際は重複の削除やインデックスの設定を検討する。

これらのポイントを意識しながらmerge関数を使うことで、より効率的かつ正確にデータフレームを結合できるでしょう。

pandasを使ったデータ分析のステップアップに向けて

merge関数を習得したら、次はpandasの他の機能についても学習を深めていきましょう。以下は、データ分析のスキルアップに役立つトピックの例です。

  • groupby()を使ったデータのグループ化と集計
  • pivot_table()を使ったピボットテーブルの作成
  • apply()を使ったカスタム関数の適用
  • matplotlib、seabornなどのライブラリを使ったデータの可視化

これらの機能を組み合わせることで、複雑なデータ処理や分析を効率的に行えるようになります。以下は、groupby()を使ったデータの集計例です。

import pandas as pd

# サンプルデータフレームの作成
data = {
    'category': ['A', 'B', 'C', 'A', 'B', 'C'],
    'value': [10, 20, 30, 40, 50, 60]
}
df = pd.DataFrame(data)

# groupby()を使ったデータの集計
grouped_df = df.groupby('category')['value'].sum().reset_index()
print(grouped_df)

出力結果:

  category  value
0        A     50
1        B     70
2        C     90

このように、pandasの各機能を使いこなせるようになると、データ分析の幅が大きく広がります。今回学んだmerge関数を活用しつつ、他の機能についても学習を深めていくことで、データ分析のプロフェッショナルを目指しましょう。