这是我上一个问题enter link description here
的扩展我有两个长度不同的数据帧df1和df2,还有两个列作为关键列。我想对这些数据帧执行以下多个操作:
id_col1 id_col2 name age sex
---------------------------------------
101 1M 21
101 3M 21 M
102 1M Mark 25
id_col1 id_col2 name age sex
-------------------------------------------
101 1M Steve M
101 2M M
101 3M Steve 25
102 1M Ria 25 M
102 2M Anie 22 F
执行操作1后,即用df2中的相应值替换df1中的NA,我应该得到以下信息:
id_col1 id_col2 name age sex
-------------------------------------------
101 1M Steve 21 M
101 3M Steve 25 M
102 1M Mark 25 M
执行操作2后,即相同键列的df1和df2中的单元格冲突,我应该得到以下信息:
id_col1 id_col2 name age sex
-------------------------------------------
101 3M 21
101 3M 25
102 1M Mark
102 1M Ria
有人可以帮助解决这些问题吗?
答案 0 :(得分:1)
使用 df1
df2
合并
df3=df2.merge(df1, left_index=True,right_index=True,suffixes=('_left', ''), how='left')
解决方案1,使用np.where传输详细信息并删除不需要的行
df3['name']=np.where(df3['name'].isna(),df3['name_left'],df3['name'])
df3['sex']=np.where(df3['sex_left'].isna(),df3['sex'],df3['sex_left'])
df4=df3[df3.index.isin(df1.index)].iloc[:,-3::]
结果
您对冲突不太清楚,因此我假设在姓名和年龄方面存在冲突。因此,我不建议使用NaN,因为它们存在于我未填充它们的地方
df3=df3.dropna(subset=['age','age_left'])
一系列布尔选择的派生数据框
df3[(df3['name_left']!=df3['name'])& df3['age_left']!=df3['age']].dropna(thresh=1, inplace=True)
答案 1 :(得分:1)
我将采用的方法与原始问题的答案非常相似。
与原始文章一样,将id列设置为索引,使用combine_first
。但是,由于combine_first
返回了两个数据框标签(即行和列)的并集,因此在应用后,请仅选择属于df1
idx = ['id_col1', 'id_col2']
df1 = df1.set_index(idx)
df2 = df2.set_index(idx)
result_1 = df1.combine_first(df2).loc[df1.index]
# result_1 outputs:
name age sex
id_col1 id_col2
101 1M Steve 21.0 M
3M Steve 21.0 M
102 1M Mark 25.0 M
要生成result_2
,请首先按照早先帖子中建议的方法进行操作:
mask = pd.notnull(df1) & ~df1.eq(df2) & pd.notnull(df2)
result_2 = pd.concat([df1[mask], df2[mask]]).dropna(how='all')
这会生成所需的数据,但是顺序与您显示的顺序略有不同,因为df1[mask]
堆积在df2[mask]
的顶部。
按索引排序以获得最终结果:
result_2.sort_index()
# outputs
name age sex
id_col1 id_col2
101 3M NaN 21.0 NaN
3M NaN 25.0 NaN
102 1M Mark NaN NaN
1M Ria NaN NaN
与第一篇文章中介绍的解决方案相比,该解决方案的唯一区别是额外的...loc[df1.index]
和result_2.sort_index()