【问题标题】:Disjoint set of records from two pandas DataFrames来自两个 pandas DataFrames 的不相交记录集
【发布时间】:2016-11-25 19:16:49
【问题描述】:

有没有一种简单的方法可以根据 MultiIndex 找到两个 pandas 数据帧之间不相交的记录集(两个原始数据帧中的每一个上会留下什么,不包括在结果内部连接中)?

我是否遗漏了一些相当明显的东西,还是我必须自己花一些时间来实现这种功能?

我试图通过找到两个数据帧的 muliIndex 键集之间的对称差异来做到这一点,但事实证明这很困难。我一直在努力让它发挥作用。我的另一个选项,看起来可能更容易一些,是添加一个虚拟的整数列,它可以充当不同的单个索引,即使在我执行 multiIndex 合并之后也会保留,这样我就可以使用 python 集合运算符这个事实上的单键。

[请注意,这与此问题相关但略有不同,因为此合并不是基于 MultiIndex 对象,而是基于数据框列中的值:How do I do a SQL style disjoint or set difference on two Pandas DataFrame objects?]

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我认为您找到对称差异的方法是可行的方法。

    In [97]: from numpy import random
    
    In [98]: arrays1 = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
       ....:           ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
    
    
    In [99]: arrays2 = [['bar', 'baz', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], [
       ....: 'one', 'one', 'two', 'three', 'one', 'two', 'one', 'three']]
    
    
    In [100]: tuples1 = zip(*arrays1)
    
    In [101]: tuples2 = zip(*arrays2)
    
    In [102]: index1 = MultiIndex.from_tuples(tuples1, names=['first', 'second'])
    
    In [103]: index2 = MultiIndex.from_tuples(tuples2, names=['first', 'second'])
    
    In [104]: df1 = pd.DataFrame(random.randn(8, 2), index=index1)
    
    In [105]: df2 = pd.DataFrame(random.randn(8, 2), index=index2)
    
    In [106]: df1
    Out[106]: 
                         0         1
    first second                    
    bar   one     0.613378 -0.400247
    baz   one    -3.005834  0.004879
          two     0.066539 -0.289100
          three  -0.020099  0.644226
    foo   one    -0.461458 -1.621812
          two     0.286655  0.110588
    qux   one     0.363648 -0.271281
          three   1.707787 -1.832602
    
    In [107]: df2
    Out[107]: 
                         0         1
    first second                    
    bar   one    -1.010482 -0.023373
    baz   one    -0.040335  1.553905
          two    -0.080283 -0.571686
          three  -0.985722 -0.795481
    foo   one     0.623122  2.124316
          two    -0.493333 -0.343462
    qux   one    -1.346753 -1.343945
          three  -0.053497 -0.382402
    
    In [108]: sym_diff = (df1.index - df2.index).union(df2.index - df1.index)
    
    In [109]: sym_diff
    Out[109]: 
    MultiIndex
    [(u'baz', u'three'), (u'qux', u'three')]
    

    我不确定为什么 MultiIndex 上没有对称差分法。

    【讨论】:

    • 好的,当我将第 103 行更改为 index2 并将第 108 行中的最后一项更改为 df1.index 时,它可以工作。唯一的问题是 MultiIndex 和我的数据帧的大小,它最终需要将近一分钟来计算 sym_diff。我认为你的方式看起来更优雅,但我最终做的却略有不同。我在合并之前重新发送了索引,然后合并了两次,第一次保留一帧的索引,第二次保留另一帧的索引。然后我在每个原始列中按索引删除了匹配的行。这是更多的代码,但花了大约 5 秒。
    • 我会在今天晚些时候写下我的解决方案,以防万一有人看到。
    • 抱歉有错别字,您在这两个帐户上都是对的。太糟糕了,我的方式太慢了。您的索引是否提前排序?我想知道这是花费最多时间还是设置操作。
    【解决方案2】:

    使用与 TomAugspurger 概述的相同测试数据

    import pandas as pd
    import numpy as np
    
    # create a test data set
    arrays1 = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
               ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
    arrays2 = [['bar', 'baz', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
               ['one', 'one', 'two', 'three', 'one', 'two', 'one', 'three']]
    tuples1 = zip(*arrays1)
    tuples2 = zip(*arrays2)
    index1 = pd.MultiIndex.from_tuples(tuples1, names=['first', 'second'])
    index2 = pd.MultiIndex.from_tuples(tuples2, names=['first', 'second'])
    df1 = pd.DataFrame(np.random.randn(8, 2), index=index1)
    df2 = pd.DataFrame(np.random.randn(8, 2), index=index2)
    

    产生以下两个表格

                         0         1
    first second                    
    bar   one    -0.579214  0.261575
          two     0.912683 -0.475463
    baz   one    -0.295739 -0.586646
          two     0.031916  0.199812
    foo   one    -0.724781 -1.245275
          two    -0.824759  2.270161
    qux   one     0.638533  0.537306
          two    -0.988444 -1.076636
    

                         0         1
    first second                    
    bar   one    -0.859494  0.214814
    baz   one    -0.446976  1.281912
          two    -0.181159  0.574126
          three   0.212799 -1.592317
    foo   one    -1.192866  1.544799
          two     1.025816  0.921364
    qux   one    -0.927700 -0.516720
          three   0.610065  0.028249
    

    那么你可以通过

    得到不相交的数据框
    df1[~df1.index.isin(df2.index)].append(df2[~df2.index.isin(df1.index)])
    

    导致

                         0         1
    first second                    
    bar   two     0.912683 -0.475463
    qux   two    -0.988444 -1.076636
    baz   three   0.212799 -1.592317
    qux   three   0.610065  0.028249
    

    这是你要求的吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-07
      • 2022-01-24
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 2016-11-25
      • 1970-01-01
      • 2022-12-18
      相关资源
      最近更新 更多