みどりのジーパン

Data Science / Data Engineering / MLOpsを勉強中

pd.mergeで同じカラムがあるとcol_x, col_y...と別カラムが生える件

概要

pandasのmergeを繰り返し行うと意図せずcolumn_x, column_y...と、元々あったcolumn_x, _yとついてきて困ったことがある人向けです。 結果的に綺麗な解決策ではないですが、結合に使用するカラム名は揃えることは徹底した方が良さそうです。

どうしたの

python機械学習の前準備をする際、特徴量生成のためにいくつかのcsvをマージすることはよくあると思います。 例えば、以下のようなデータがあったとします。 dsが日付、yがその日の値を表現します。

f:id:green-j:20220402105332p:plain

これにそれぞれ別のソースから獲得されるflag_1flag_2というフラグを用意してmergeさせてみます(というケースを仮定します)。 データ生成コードはこちら。

feature_1 = pd.DataFrame({
    "target_ds": df["ds"],
    "flag_1": np.random.binomial(1, 0.25, len(df))
})
feature_2 = pd.DataFrame({
    "target_ds": df["ds"],
    "flag_2": np.random.binomial(1, 0.1, len(df))
})
flag_df_list = [feature_1, feature_2]
})

これをいざマージして中身を見てみると、元々あったtarget_dsというカラムがなくなり、代わりにtarget_ds_xtarget_ds_yの、意図しないカラムが作られてしまっています。

for _df_flag in flag_df_list:
    df = pd.merge(
        left=df,
        right=_df_flag,
        how="left",
        left_on="ds",
        right_on="target_ds"
    )
df.head()

f:id:green-j:20220402113053p:plain

すでにdsというカラムがあるので、

どうするの

mergeするkeyとなるカラムの名称を全て揃えておけば問題なさそう。 以下のように、feature_1などの日付カラム名dsに統一したところうまくいった。

feature_1 = pd.DataFrame({
    "ds": df["ds"],
    "flag_1": np.random.binomial(1, 0.25, len(df))
})
feature_2 = pd.DataFrame({
    "ds": df["ds"],
    "flag_2": np.random.binomial(1, 0.1, len(df))
})
flag_df_list = [feature_1, feature_2]

for _df_flag in flag_df_list:
    df = pd.merge(
        left=df,
        right=_df_flag,
        how="left",
    )
df.head()

f:id:green-j:20220402123836p:plain

pd.mergeする時にleft_onright_onの両方を使おうとした際は気をつけた方が良さそうです。 業務で詰まったポイントを再現するためこんな話の展開になっているけど、まあ普通に考えてfeature_1のカラム名をわざわざtarget_dsにするなんて有り得ないよなというself-ツッコミで終わり。

参考

pandas.pydata.org

yaju3d.hatenablog.jp

github.com

(一応コード) github.com