合并两个pandas嵌套框,只保留有差异的列和行

eqzww0vc  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(168)

我正在寻找一种有效的方法来比较两个嵌套框,在某种程度上,只有具有不同值的行和列将保留。假设嵌套框是:
df1:
| 昵称|考试日|结果_1|结果_2| pre_result_1|
| --|--|--|--|--|
| 帕特里克|2023-01-01 2023-01-01| 1 | 10 | 123 |
| 帕特里克|2023-01-02 2023-01-02|我的天| 20 | 123 |
| 帕特里克|2023-01-03 2023-01-03| 3 | 30 | 123 |
| 帕特里克|2023-01-04 2023-01-04| 4 | 40 | 123 |
df2:
| 昵称|考试日|结果_1|结果_2| pre_result_1|
| --|--|--|--|--|
| 帕特里克|2023-01-01 2023-01-01| 1 | 10 | 123 |
| 帕特里克|2023-01-02 2023-01-02|99| 20 | 123 |
| 帕特里克|2023-01-03 2023-01-03| 3 | 30 | 123 |
| 帕特里克|2023-01-04 2023-01-04| 4 | 40 | 123 |
它们之间有一个区别,在第2行,列:result_1到目前为止,我想出了:

pets_diff = df1.merge(
            df2,
            indicator=True,
            how="outer",
        )
pets_diff = pets_diff[lambda x: x["_merge"] != "both"]

字符串
这将删除所有匹配的行,只留下那些有差异的行,如下所示:
| 昵称|考试日|结果_1|结果_2| pre_result_1|_合并|
| --|--|--|--|--|--|
| 帕特里克酒店|2023-01-02 -02 - 01|我的天| 20 | 123 |left_only|
| 帕特里克酒店|2023-01-02 -02 - 01|99| 20 | 123 |仅右|
最后我想用下面的框架来结束:
| 昵称|考试日|结果_1|
| --|--|--|
| 帕特里克酒店|2023-01-02 -02 - 01|我的天|
| 帕特里克酒店|2023-01-02 -02 - 01|99|
注意,所有具有相同值的行和列都消失了。我想保留dimension列:pet_nameexam_day,并删除所有具有匹配值的其他列。请注意,有300多个列可能具有不同的值和名称(result_1,result_2,pre_result_1,post_exam_33等)。

mum43rcc

mum43rcc1#

使用DataFrame.compare

out = (df1.set_index(['pet_name','exam_day'])
          .compare(df2.set_index(['pet_name','exam_day']), align_axis=0)
          .droplevel(-1)
          .reset_index())

print (out)
#40 in df2 is changed to 100
  pet_name    exam_day  result_1  result_2
0  Patrick  2023-01-02       2.0       NaN
1  Patrick  2023-01-02      99.0       NaN
2  Patrick  2023-01-04       NaN      40.0
3  Patrick  2023-01-04       NaN     100.0

字符串

详情

print(df1.set_index(['pet_name','exam_day'])
          .compare(df2.set_index(['pet_name','exam_day']), align_axis=0))
                           result_1  result_2
pet_name exam_day                            
Patrick  2023-01-02 self        2.0       NaN
                    other      99.0       NaN
         2023-01-04 self        NaN      40.0
                    other       NaN     100.0

643ylb08

643ylb082#

另一种可能的解决方案,基于numpypd.concat

idxx, idxy = np.where(df1.values != df2.values)
idxy = np.unique(idxy)
pd.concat([df1.iloc[np.tile(idxx, 2),:2], 
           pd.concat([df1.iloc[(idxx, idxy)], df2.iloc[(idxx, idxy)]])], axis=1)

字符串
输出量:

pet_name    exam_day  result_1
1  Patrick  2023-01-02         2
1  Patrick  2023-01-02        99

相关问题