【Pandas】同じ列名を持つ2つのDataFrameにおいて、共通する行の抽出・異なる行の抽出・重複を排除して統合する方法をまとめた
当サイトではアフィリエイト広告を利用しています
タイトル通りでニッチな例ですが、ドンピシャな例がなく構築に手間取ったので備忘録として記録しておきます。
用途としては事務方がエクセルで作られた名簿において、名簿を統合したり、更新の判定などに使う、といったものですね。
確認した環境
- Python: 3.10
- Pandas: 2.2.3
Pythonスクリプト
対象となるDataFrame
以下の2つのDataFrameを想定します。同じ列名としてA,Bを持っています。
このDataFrameから、共通する行の抽出、異なる行の抽出、統合して重複を排除したものの抽出の3通りの操作を行います。
import pandas as pd
# DataFrame作成
df1 = pd.DataFrame({"A": [1, 2, 3, 4, 5], "B": [True, True, True, True, True]})
df2 = pd.DataFrame({"A": [1, 2, 3, 4, 5], "B": [True, False, True, False, False]})
# print(df1)
# A B
# 0 1 True
# 1 2 True
# 2 3 True
# 3 4 True
# 4 5 True
# print(df2)
# A B
# 0 1 True
# 1 2 False
# 2 3 True
# 3 4 False
# 4 5 False
# 2つのDataFrameが同じ列名を持っていることが前提
assert list(df1.columns) == list(df2.columns)
基本的にはpd.concat()
やpd.merge()
を用いれば実施可能ですが、差分判定にちょっと手間取りました。
2つのDataFrameを統合して重複排除(和集合)
pd.concat()
とdrop_duplicates()
で実現可能ですが、統合前に重複があればそれも消えるので注意です。
# 2つのDataFrameを連結して重複排除(和集合)
# ※元々重複行があった場合にもdropするので注意
df_merge = pd.concat([df1, df2]).drop_duplicates()
# print(df_merge)
# 0 1 True
# 1 2 True
# 2 3 True
# 3 4 True
# 4 5 True
# 1 2 False
# 3 4 False
# 4 5 False
Inner Mergeを用いるパターン(積集合)
pd.merge()
でinner指定をすれば共通する行の抽出は可能です。
# 全列でinner mergeしてやれば共通行だけ残る(積集合)
df_intersction = pd.merge(df1, df2, how="inner", on=list(df1.columns))
# print(df_intersction)
# A B
# 0 1 True
# 1 3 True
Outer Mergeを用いるパターン(積集合・和集合・差集合)
pd.merge()
でouter指定をすればすべてのパターンに対応できるようです。
# mergeするときにhow=outer, indicator=Trueとすれば由来がわかる
df_merge = pd.merge(df1, df2, how="outer", indicator=True)
# print(df_merge)
# A B _merge
# 0 1 True both
# 1 2 False right_only
# 2 2 True left_only
# 3 3 True both
# 4 4 False right_only
# 5 4 True left_only
# 6 5 False right_only
# 7 5 True left_only
# 2つのDFの和集合も得ることができる
df_union = df_merge[list(df1.columns)]
# df1にしかない行の抽出(差集合)
df1_only = df_merge[df_merge["_merge"] == "left_only"][list(df1.columns)]
# print(df1_only)
# A B
# 2 2 True
# 5 4 True
# 7 5 True
# df2にしかない行の抽出(差集合)
df2_only = df_merge[df_merge["_merge"] == "right_only"][list(df2.columns)]
# print(df2_only)
# A B
# 1 2 False
# 4 4 False
# 6 5 False
# df1とdf2に共通する行の抽出(積集合)
df_intersction = df_merge[df_merge["_merge"] == "both"][list(df2.columns)]
# print(df_intersction)
# A B
# 0 1 True
# 3 3 True
まとめ
- Python & Pandasで2つのDataFrameに対する操作を行った
- 重複する行の抽出、異なる行の抽出、統合して重複削除の3通り
pd.merge
でouterを用いれば3操作のいずれも対応できる