如何在 Pandas Python 中合并时避免笛卡尔坐标

Posted

技术标签:

【中文标题】如何在 Pandas Python 中合并时避免笛卡尔坐标【英文标题】:How to avoid Cartesian while merging in Pandas Python 【发布时间】:2019-02-16 01:45:55 【问题描述】:

我正在尝试合并 2 个数据集 X 和 Y。数据集 X 具有包含重复值的连接键列。数据集 Y 具有连接键列和一个附加列。数据集图像已在下面上传。问题是我想避免笛卡尔积,因为数据集 X 中存在重复项。我附上了下面的结果数据集图像。这可以通过使用 for 循环手动合并来手动完成,但这很耗时。任何人都可以提供更好的方法

【问题讨论】:

我读你的问题越多,我就越不明白你在问什么。你想合并两个DataFrames?为什么要使用笛卡尔积来做到这一点?请参阅此处here 合并的工作原理。默认不涉及任何产品。 笛卡尔积我的意思是,所有值为 610462 的 EMM_ID 将获得 ID_Home 值 80100。相反,我想要仅第一个 EMM_ID 610462 获取值 80100,其余 EMM_ID 610462 应为 NaN。我希望我现在有道理,很难解释。谢谢 【参考方案1】:

在这种情况下,由于只需要带一列,.map 可能更合适。我们取每个 EMM_ID 组中的第一个值,并仅映射该值。对齐索引确保其余部分变为NaN

样本数据

import pandas as pd
import numpy as np
df_x = pd.DataFrame('EMM_ID': [610462, 610462, 610462, 610462, 61000, 61000],
                     'ID_home': [np.NaN, np.NaN, np.NaN, np.NaN, np.NaN, np.NaN])
df_y = pd.DataFrame('EMM_ID': [610462, 61000], 'ID_home': [81000, 18])

代码

df_x['ID_home'] = df_x.groupby('EMM_ID').head(1).EMM_ID.map(df_y.set_index('EMM_ID').ID_home)

输出:df_x

   EMM_ID  ID_home
0  610462  81000.0
1  610462      NaN
2  610462      NaN
3  610462      NaN
4   61000     18.0
5   61000      NaN

如果您需要引入多个列,则可以拆分 DataFrame,与子集合并,然后连接回一个 DataFrame。

df_x = pd.DataFrame('EMM_ID': [610462,610462,610462,610462, 61000, 61000],
                     'ID_home': [np.NaN, np.NaN, np.NaN, np.NaN, np.NaN, np.NaN])
df_y = pd.DataFrame('EMM_ID': [610462, 61000], 'ID_home': [81000, 18], 'Val_2': ['A', 'F'])

to_merge = df_x.groupby('EMM_ID').head(1)
keep = df_x[~df_x.index.isin(to_merge.index)]

pd.concat([keep, to_merge[['EMM_ID']].merge(df_y)], sort=False).sort_index() 

输出:

   EMM_ID  ID_home Val_2
0  610462  81000.0     A
1  610462      NaN   NaN
1   61000     18.0     F
2  610462      NaN   NaN
3  610462      NaN   NaN
5   61000      NaN   NaN

【讨论】:

【参考方案2】:

使用@Alollz 设置:

df_x = pd.DataFrame('EMM_ID': [610462, 610462, 610462, 610462, 61000, 61000],
                     'ID_home': [np.NaN, np.NaN, np.NaN, np.NaN, np.NaN, np.NaN])
df_y = pd.DataFrame('EMM_ID': [610462, 61000], 'ID_home': [81000, 18])

您可以创建一个新的“密钥”来加入 cumcount。

colkey = 'EMM_ID'
df_x = df_x.assign(colkey=df_x.groupby(colkey).cumcount())
df_y = df_y.assign(colkey=df_y.groupby(colkey).cumcount())

df_x[['EMM_ID','colkey']].merge(df_y, on=['EMM_ID','colkey'], how='left')

输出:

   EMM_ID  colkey  ID_home
0  610462       0  81000.0
1  610462       1      NaN
2  610462       2      NaN
3  610462       3      NaN
4   61000       0     18.0
5   61000       1      NaN

【讨论】:

以上是关于如何在 Pandas Python 中合并时避免笛卡尔坐标的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 python 中的 pandas 合并重现 R 中 foverlaps 的相同输出?

如何使用 Python Pandas 合并多个 CSV 文件

如何在 python pandas 中重新构造它?合并,取消堆叠还是啥?

python--pandas合并与连接

在 Python 中使用 Pandas 合并时间序列数据帧及其集体附加注释

求助,使用Python合并多个EXCEL表格时,如果表格有密码,密码已知,该怎么通过pandas合并,