データセットのマージ操作では、二つのデータセットのインデックスの一部、または全てが重複しているケースも考えられる。

下記のような二つのデータセットがあるとする。

import pandas as pd
import numpy as np

s1 = pd.Series([np.nan, 2.5, 0.0, 3.5, 4.5, np.nan],
              index=['f', 'e', 'd', 'c', 'b', 'a'])
# f    NaN
# e    2.5
# d    0.0
# c    3.5
# b    4.5
# a    NaN
# dtype: float64

s2 = pd.Series([0., np.nan, 2., np.nan, np.nan, 5.],
              index=['a', 'b', 'c', 'd', 'e', 'f'])
# a    0.0
# b    NaN
# c    2.0
# d    NaN
# e    NaN
# f    5.0
# dtype: float64

このようにインデックスが重複したデータをマージする場合の方法として、Numpyのwhere関数を使う方法がまず挙げられる。

where関数

where関数は行列指向のif文で、今回のケースでは下記のように使う。

np.where(pd.isnull(s1), s2, s1)
# array([0. , 2.5, 0. , 3.5, 4.5, 5. ])

第一引数に条件を指定し、条件がTrueの場合は第二引数の値を、Falseの場合は第三引数の値を返す。
この場合、pd.isnull(s1)が指定されているため、s1のデータが欠損値であればs2から、そうでなければs1からデータを取得し、上記例のとおり欠損値を含まない配列を取得することができる。

combine_firstメソッド

シリーズにはcombine_firstというメソッドも用意されており、このメソッドを使うことでNumpyのwhere関数と同等の処理をおこなうことができる。

またwhere関数と違い、インデックス順に整列された結果を得ることができる。

s2.combine_first(s1)
# a    0.0
# b    4.5
# c    2.0
# d    0.0
# e    2.5
# f    5.0
# dtype: float64

データフレームをマージする場合

データフレームにもcombine_firstメソッドが用意されており、同様に扱うことができる。

マージ処理のイメージとしては、メソッド呼び出し元のオブジェクトに含まれる欠損値を、引数に与えたオブジェクトで補完していると考えると分かりやすいだろう。

import pandas as pd
import numpy as np

df1 = pd.DataFrame({'a': [1., np.nan, 5., np.nan],
                   'b': [np.nan, 2., np.nan, 6.],
                   'c': range(2, 18, 4)})
#      a    b   c
# 0  1.0  NaN   2
# 1  NaN  2.0   6
# 2  5.0  NaN  10
# 3  NaN  6.0  14

df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.],
                   'b': [np.nan, 3., 4., 6., 8.]})
#      a    b
# 0  5.0  NaN
# 1  4.0  3.0
# 2  NaN  4.0
# 3  3.0  6.0
# 4  7.0  8.0

df1.combine_first(df2)
#      a    b     c
# 0  1.0  NaN   2.0
# 1  4.0  2.0   6.0
# 2  5.0  4.0  10.0
# 3  3.0  6.0  14.0
# 4  7.0  8.0   NaN