在 Pandas Python 中合并时如何避免笛卡尔
How to avoid Cartesian while merging in Pandas Python
我正在尝试合并 2 个数据集 X 和 Y。数据集 X 的连接键列具有重复值。数据集 Y 具有连接键列和一个附加列。数据集图像已在下面上传。问题是由于数据集 X 中存在重复项,我想 避免笛卡尔积 。我在下面附上了结果数据集图像。这可以通过使用 for 循环手动合并来手动完成,但这很耗时。谁能提供更好的方法
这样的话,只需要带一栏,.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
使用@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]})
您可以创建一个新的 'key' 来加入 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
我正在尝试合并 2 个数据集 X 和 Y。数据集 X 的连接键列具有重复值。数据集 Y 具有连接键列和一个附加列。数据集图像已在下面上传。问题是由于数据集 X 中存在重复项,我想 避免笛卡尔积 。我在下面附上了结果数据集图像。这可以通过使用 for 循环手动合并来手动完成,但这很耗时。谁能提供更好的方法
这样的话,只需要带一栏,.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
使用@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]})
您可以创建一个新的 'key' 来加入 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