【问题标题】:Get unmerged data from source tables从源表中获取未合并的数据
【发布时间】:2017-11-07 13:58:27
【问题描述】:

我有两个数据框:

df1 = (data = {'Invoice' : [1, 2, 3, 4, 5],
                            'Value' : [10, 25, 40, 10, 15]})

     Invoice    Value  Param
0        1     10      0
1        2     25      0
2        3     40      0
3        4     10      0
4        5     15      0

df2 = (data = {'Invoice' : [2, 3, 5, 2],
                'Value' : [25, 15, 15,25],
                'TestData': ["A",'B','C','D']})

   Invoice    TestData  Value  Param
0        2        A     25      0
1        3        B     15      0
2        5        C     15      0
3        2        D     25      1

我不想将 df2 中的 2 号发票与 df1 中的单次合并两次,所以:

df1["Param"]=df1.groupby(["Invoice","Value"]).cumcount()
df2["Param"]=df2.groupby(["Invoice","Value"]).cumcount()

合并后:

df3 = (df1,df2, left_on=["Invoice","Value","Param"], right_on=["Invoice","Value","Param"])`

有最终的、合并的、数据框:

     Invoice    Value   Param TestData 
0     2      25      0      A 
1     5      15      0      C

现在我想从 df1 获取未合并的数据:

df1[(~df1.Invoice.isin(df3.Invoice))&(~df1.Value.isin(df3.Value))]`

它适用于 df1:

    Invoice Value   Param
0   1     10      0
2   3     40      0
3   4     10      0

但结果为空数据帧的 df2 失败:

df2[(~df2.Value.isin(df3.Value))&(~df2.Invoice.isin(df3.Invoice))]`

就我检查这一点而言,我认为比较运行“两次”而不是一次(& 运算符) - 首先检查每张发票的代码编号,然后再次独立检查值而不是检查同时满足两个条件。

你知道如何以这种形状获得未合并的 df2:

         Invoice   TestData   Value   Param
1        3        B     15      0
3        2        D     25      1

【问题讨论】:

    标签: python pandas dataframe merge


    【解决方案1】:

    更新了“参数”添加到合并

    一种方法是使用how='outer'indicator=True 从两个数据框中查找“未合并”数据。这将向您显示一个数据框,其中包含一个包含三个值的列 _merge,“both”表示成功合并,“left_only”表示来自 df1 的“未合并”数据,“right_only”表示来自 df2 的“未合并”数据。

    例子:

    df1 = pd.DataFrame(data = {'Invoice' : [1, 2, 3, 4, 5],
                                'Value' : [10, 25, 40, 10, 15]})
    
    df2 = pd.DataFrame(data = {'Invoice' : [2, 3, 5, 2],
                    'Value' : [25, 15, 15,25],
                    'TestData': ["A",'B','C','D']})
    df1["Param"]=df1.groupby(["Invoice","Value"]).cumcount()
    df2["Param"]=df2.groupby(["Invoice","Value"]).cumcount()
    
    df3 = pd.merge(df1,df2, left_on=["Invoice","Value","Param"], 
                   right_on=["Invoice","Value","Param"],
                   how='outer', indicator=True)
    
    df3
    

    输出:

       Invoice  Value  Param TestData      _merge
    0        1     10      0      NaN   left_only
    1        2     25      0        A        both
    2        3     40      0      NaN   left_only
    3        4     10      0      NaN   left_only
    4        5     15      0        C        both
    5        3     15      0        B  right_only
    6        2     25      1        D  right_only
    

    获取内部连接完整合并数据:

    df3.query('_merge == "both"')
    

    输出:

       Invoice  Value  Param TestData _merge
    1        2     25      0        A   both
    4        5     15      0        C   both
    

    从 df1 获取“未合并”的数据

    df3.query('_merge == "left_only"')
    
       Invoice  Value  Param TestData     _merge
    0        1     10      0      NaN  left_only
    2        3     40      0      NaN  left_only
    3        4     10      0      NaN  left_only
    

    并且,从 df2 获取“未合并的数据”

    df3.query('_merge == "right_only"')
    
       Invoice  Value  Param TestData      _merge
    5        3     15      0        B  right_only
    6        2     25      1        D  right_only
    

    【讨论】:

    • 非常感谢您的回答!非常抱歉,Scott,但在我看到你的最后一个结果表后,我意识到我在合并代码中忘记了“Param”,但输出数据帧和其他一切都很好。我已经将它添加到代码中,所以现在可以了。我会检查你的解决方案,但我想我在问问题之前就这样做了——“参数”变化很大:/
    • 你是对的!非常感谢您的帮助!!!我不明白它是如何工作的,但我会学习的:)
    • 哦……它做了一个完整的外部连接。您熟悉数据库外连接吗?然后,它会标记可能已内连接的记录,并根据其来源标记那些未内连接的记录。
    • 谢谢!现在很清楚了:)我是python、sql等方面的新手(学习了两周),所以每一个新想法都很宝贵:)
    • 这并不能真正回答问题,因为最终结果是来自 df3 的行。您将如何实现这一点并从原始 df1 中获取未标记的行?
    猜你喜欢
    • 2020-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多