【问题标题】:python pandas - get matching and non matching records between two dataframespython pandas - 获取两个数据帧之间的匹配和不匹配记录
【发布时间】:2018-10-21 10:35:42
【问题描述】:

我是在 python 中使用 pandas 的新手,但我对使用 python 有很好的了解。

我有两个数据帧,我必须从中获取匹配记录和不匹配记录到新数据帧中。

例子:

DF1:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999
4  DDD  1237   05-09-2000 450000

DF2:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999
4  DDD  1237   05-09-2000 540000

而且,这里的主键是 ID 和名称(实际上键的数量可能会有所不同),我需要得到 ​​p>

Match_df:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999

不匹配_df:

ID Name Number    DOB     Salary
4  DDD  1237   05-09-2000 540000

我已经尝试了所有可能的方法,例如

pd.merge(df1, df2, left_on=[ID,Name],right_on=[ID,Name], how='inner')

这会产生两个数据帧中的所有唯一键。但这也会产生不匹配的记录。

但我得到了这个结果:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999
4  DDD  1237   05-09-2000 540000

第 4 条记录也包含在内。

这里,只有工资列是变化的,但在实时,它可能是要比较的列的列表。

据此,我只需要将匹配的记录获取到matched_df,将不匹配的记录获取到mismatch_df。

请帮我做这件事。

注意:我的数据集可能是一个庞大的数据集(两个数据集中都有 1 亿条记录),所以请给我一个有效的方法来减少执行时间。

提前致谢。

【问题讨论】:

  • 您有多个答案,您可以使用其中一个从未回答队列中清除此问题。
  • 是的,但实际上我仍在解决这个问题。这就是为什么我仍然持有这个。

标签: python pandas compare


【解决方案1】:

您的问题的简单答案是df1.where

注意:具有 NaN 的结果单元格不满足条件,即它们在两个数据帧中不相等。具有实际值的是两个数据帧中相等的那些

>>> df1.where(df1.Salary==df2.Salary)
          DoB   ID  Name    Salary
0  12-05-1996  1    AAA  100000.0
1  16-08-1997  2    BBB  200000.0
2  24-04-1998  3    CCC  389999.0
3         NaN  NaN  NaN       NaN

在使用pd.merge 时:如果您只想在没有列或索引级别的情况下合并 df1 和 df1,那么它将默认为两个 DataFrame 中列的交集。

>>> pd.merge(df1, df2)
          DoB  ID Name  Salary
0  12-05-1996   1  AAA  100000
1  16-08-1997   2  BBB  200000
2  24-04-1998   3  CCC  389999

如果您希望加入列或索引级别,请使用on

 >>> pd.merge(df1, df2, on="Salary")
        DoB_x  ID_x Name_x  Salary       DoB_y  ID_y Name_y
0  12-05-1996     1    AAA  100000  12-05-1996     1    AAA
1  16-08-1997     2    BBB  200000  16-08-1997     2    BBB
2  24-04-1998     3    CCC  389999  24-04-1998     3    CCC

对于df2中的不匹配:您可以选择isin(dict)方法:

>>> df2[~df2.isin(df1.to_dict('l')).all(1)]
          DoB  ID Name  Salary
3  05-09-2000   4  DDD  540000

Mabel 给出的另一种方式。

df2[~df2.isin(df1).all(axis=1)]

【讨论】:

  • 感谢您抽出宝贵时间回答我的问题,我投了赞成票,但我认为这不会反映出我是新的贡献者...
【解决方案2】:
# pick index keys and compare column(s)
keys = ['ID', 'Name']
# if comparing all columns:
col_list = [col for col in df1.columns if col not in keys]
# # if comparing specific columns:
# col_list = ['Salary', 'DOB']

# extend keys with col_list for next step
sel_cols = keys.copy()
sel_cols.extend(col_list)

# set a multi-index with keys
# to dataframes with col_list columns
dfa = df1[sel_cols].set_index(keys)
dfb = df2[sel_cols].set_index(keys)

# make an equivalency boolean mask
dfa.update(dfb)
mask = np.equal(df1[col_list].values, dfa.values).all(axis=1)

# slice df1 with mask
Match_df = df1[mask]
Mismatch_df = df1[~mask]

【讨论】:

  • 这会抛出“异常:无法处理非唯一的多索引!”当我通过 cols 列表代替“salary”时出错.....
  • OK 不明白您要比较多个列。待机。
  • 我很快会进一步更新以删除循环 - 这对您现在有效吗?
  • 删除了循环,便于比较所有列或仅比较选定的列。
  • 非常感谢,你的太棒了。我只需要进行更多更改即可按要求完成工作。太感谢了!!!!
【解决方案3】:

我的解决方案会有点不同,只需从其他数据集中复制工资。

如:

DF1["Salary2"] = DF2["Salary"]

MatchDF = DF1[DF1["Salary"] == DF1["Salary2"]]
MisMatchDF = DF1[DF1["Salary"] != DF1["Salary2"]]

【讨论】:

  • 但实际上我的真实数据集可能包含“n”个要检查的列,这样做会使我的代码硬编码,还可能导致性能不佳......
  • 我的意思是更多你应该尝试合并但保持工资列不变,然后在事后进行比较。可能会更容易。不过我也是新手
  • 感谢您的意见,我投了赞成票,但我认为这不会反映出我是新的贡献者...
【解决方案4】:

获得比赛:

>> df1.merge(df2)

ID Name  Number         DOB  Salary
0   1  AAA    1234  12-05-1996  100000
1   2  BBB    1235  16-08-1997  200000
2   3  CCC    1236  24-04-1998  389999

对于不匹配选择df2 中的行:

>> df2[~df2.isin(df1).all(axis=1)]

   Name  Number         DOB  Salary
ID                                 
4   DDD    1237  05-09-2000  540000

【讨论】:

    猜你喜欢
    • 2022-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 2021-09-15
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    相关资源
    最近更新 更多