3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【python】pandasのmerge備忘録

Posted at

1. はじめに

pandasmergeの挙動についてよく忘れて何回も調べるはめになるのでまとめておく.(pandasに限った話ではないが)

2.環境

  • python 3.6.0
  • pandas 0.23.4

3.merge

実際にどう処理されるかは別として,以下のように考えるとわかりやすい.

  1. onで指定した列からインデックス集合を作る.
  2. インデックス集合の要素を一つとり,onで指定した列がその値をとる行を抽出.
  3. onで指定した列以外の列の直積集合がmerge後のdatadrameの行として追加される.
  4. 2,3をインデックス集合の全ての要素に対して繰り返す.

1のインデックス集合の作り方によって,inner, outer, left, rightがある.
それ以降についてはどれも共通.

例となるdataframeを準備

import pandas as pd

left_df = pd.DataFrame({"idx": [1,1,1], "left_val": [100,101,102]})
right_df = pd.DataFrame({"idx": [1,1,1], "right_val": [103,104,105]})

# In [9]: left_df
# Out[9]:
#    idx  left_val
# 0    1       100
# 1    1       101
# 2    1       102

# In [10]: right_df
# Out[10]:
#    idx  right_val
# 0    1        103
# 1    1        104
# 2    1        105

とりあえず結果の確認

how = "inner"
merged_df = left_df.merge(right_df, on="idx", how=how)

# In [11]: merged_df
# Out[11]:
#    idx  left_val  right_val
# 0    1       100        103
# 1    1       100        104
# 2    1       100        105
# 3    1       101        103
# 4    1       101        104
# 5    1       101        105
# 6    1       102        103
# 7    1       102        104
# 8    1       102        105

1.onで指定した列からインデックス集合を作る.

on="idx"とした時,インデックス集合は

set(left_df["idx"]) | set(right_df["idx"])

の部分集合となるように作る.

howオプションごとに以下の評価式の右辺のようにインデックス集合を作る.
以下の評価は,全てTrueとなる.

# inner
set(merged_df["idx"]) == set(left_df["idx"]) & set(right_df["idx"])

# outer
set(merged_df["idx"]) == set(left_df["idx"]) | set(right_df["idx"])

# left
set(merged_df["idx"]) == set(left_df["idx"])

# right
set(merged_df["idx"]) == set(right_df["idx"])

2.インデックス集合の要素を一つとり,onで指定した列がその値をとる行を抽出.

idxset = set(merged_df["idx"])
# In [20]: idxset
# Out[20]: {1}

idx = idxset.pop()
# idx = 1

left_df_idx = left_df.query(f"idx == {idx}")
right_df_idx = right_df.query(f"idx == {idx}")

# In [12]: left_df_idx
# Out[12]:
#    idx  left_val
# 0    1       100
# 1    1       101
# 2    1       102

# In [13]: right_df_idx
# Out[13]:
#    idx  right_val
# 0    1        103
# 1    1        104
# 2    1        105

ここで,left_dfまたはright_dfに対応する行がない時,NaNとなる.
innerの時は常にlen(left_df_idx) > 0かつlen(right_df_idx) > 0なので問題ないが,それ以外にした時はlen(left_df_idx) >= 0かつlen(right_df_idx) >= 0となるのであり得る.

3.onで指定した列以外の列の直積集合がmerge後のdatadrameの行として追加される.

merged_df_idx = merged_df.query(f"idx == {idx}")

# In [23]: merged_df_idx
# Out[23]:
#    idx  left_val  right_val
# 0    1       100        103
# 1    1       100        104
# 2    1       100        105
# 3    1       101        103
# 4    1       101        104
# 5    1       101        105
# 6    1       102        103
# 7    1       102        104
# 8    1       102        105

直積集合なので以下の関係が成り立つ.

len(merged_df_idx) == len(left_df_idx) * len(right_df_idx)
# 9 = 3*3

この例の場合,

{100, 101, 102} × {103, 104, 105} = {(100, 103), (100, 104), (100, 105),
                                     (101, 103), (101, 104), (101, 105),
                                     (102, 103), (102, 104), (102, 105)}

となっている.

4. 2,3をインデックス集合の全ての要素に対して繰り返す.

これを全てのインデックス集合に対して繰り返したdataframeが,merge後のdataframeになる.(この例だと1回で終了してるが)

3
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?