熊猫强制对包含重复键的列进行一对一合并

时间:2018-12-24 10:49:00

标签: python pandas dataframe join merge

我有两个Dataframes,df1:

| ID        | Invoice   |
-------------------------
| X\191     | 4         |
| R\192     | 4         |
| 733       | 1         |
| X215      | 3         |
| BL000002  | 3         |

df2:

| ID        | Invoice   |
-------------------------
| X191      | 4         |
| X215      | 3         |
| BL000002  | 3         |

我应该将它们一对一合并以得到:

| ID        | Invoice   | ID        |
-------------------------------------
| X\191     | 4         | X191      |
| X\192     | 4         |           |
| 733       | 1         |           |
| X215      | 3         | X215      |
| BL000002  | 3         | BL000002  |

但是当我进行外部合并时,会得到重复的值

import pandas as pd
dict1 = {"ID": ["X\\191","R\\192","733","X215","BL000002"], "Inv": [4,4,1,3,3]}
df1 = pd.DataFrame.from_dict(dict1)

dict2 = {"ID": ["X191","X215","BL000002"], "Inv": [4,3,3]}
df2 = pd.DataFrame.from_dict(dict2)

some_df = pd.merge(df1, df2, on = 'Inv', how='outer')

输出如下:

    ID_x    Inv    ID_y
X\191       4      X191
X\192       4      X191
733         1       NaN
X215        3      X215
X215        3  BL000002
BL000002    3      X215
BL000002    3  BL000002

我该如何合并,以使它一对一地结合在一起,而不是混合搭配。

我不能在合并中使用任何其他列,因为它们的实际数据会有所不同。

编辑和说明 对不起。我还不够清楚。列ID不一致。我也不能保证它永远都是子字符串。但是发票值必须相同。这是人类输入的一年多时间,大约有1.5万行。我需要对它们进行排序,以使具有相同发票值的发票彼此相邻,因此,当其中一个数据框(最初是excel工作表)中缺少某些内容时,手动验证会更容易

3 个答案:

答案 0 :(得分:2)

我认为简单的列表查找就能解决问题:

df1['new_id'] = df1.apply(lambda row: row['ID'] if row['ID'] in df2['ID'].tolist() else "", axis=1)

     ID  Invoice new_id
0  X191        4   X191
1  X192        4       
2  X212        1       
3  X215        3   X215
4  X319        3   X319

找到要删除的东西后,您可以做(我假设ID为\.,'@'):

df['ID'] = df['ID'].str.replace(r'\\|\.|@', '')

答案 1 :(得分:1)

您需要另外一个基于cumcount的列:

u = df1.assign(Cnt=df1.groupby('Inv').cumcount())
v = df2.assign(Cnt=df2.groupby('Inv').cumcount())
u.merge(v, on=['Inv', 'Cnt'], how='left').drop('Cnt', 1)

       ID_x  Inv      ID_y
0     X\191    4      X191
1     R\192    4       NaN
2       733    1       NaN
3      X215    3      X215
4  BL000002    3  BL000002

答案 2 :(得分:0)

尝试以下方法:

您正在寻找pandas.merge_asof。它允许您在一个键上组合2个DataFrame,在这种情况下是时间,而不要求它们完全匹配。您可以选择一个优先顺序来确定比赛方向,但是在这种情况下,很明显您想要最接近的

>>> pd.merge_asof(df2.sort_values('Inv'), df1.sort_values('Inv'), on='Inv', direction='nearest')
  ID_x  Inv  ID_y 
0  215    3  X319
1  319    3  X319
2  191    4  X192

看看here,是从@借来的 ALollz