比较长度不等的两个数据帧的行

时间:2017-10-08 19:58:35

标签: python python-3.x pandas

我对熊猫很新,并希望得到一些关于如何以最佳方式解决问题的反馈。我试图从两个不等长度的数据帧中评估两个列的值,以找到两种情况:

    data_set_2中的
  1. id1 in data_set_2中不存在。
  2. data_set_1中不存在
  3. (id1,id2)data_set_2中的组合。
  4. 复杂性的一点是我想避免使用apply或loop方法。这些数据集可能会变得非常大(以下示例有意简化),我的理解是可以采用更有条理的方法来处理这个问题。

    data_set_1 = pd.DataFrame({"id1": ["A", "B", "C", "D"], "id2": ["1", "2", "2", "1"]})
    data_set_2 = pd.DataFrame({"id1": ["A", "B", "F", "C", "D", "E"], "id2": ["1", "1", "2", "1", "1", "2"],"id3": ["1","2","3","4","5","6"]})
    

    我期待的回报:

    1. E, F
    
    2.
    (B, 1)
    (F, 2)
    (C, 1)
    (E, 2)
    

    到目前为止我尝试的是以下内容:

    获取data_set_1中不存在的产品:

    data_set_2.loc[~(data_set_2.id1.isin(data_set_1.id1))] 
    

    (这是我不确定这是否是最佳方式) - 获取data_set_1中不存在的id1,id2组合:

    我尝试了一个isin语句,似乎两个数据帧的长度似乎是一个问题,因为pandas将评估两个数据帧之间的相同索引行,并且它独立地评估每个列。

    我发现我可以将多个列值索引为:

    data_set_2.set_index(["id1", "id2"], inplace=True,drop=False)
    data_set_1.set_index(["id1", "id2"], inplace=True,drop=False)
    

    让我这样做:

    ~data_set_2[["id1","id2"]].isin(data_set_1)
    A   1    False  False
    B   1     True   True
    F   2     True   True
    C   1     True   True
    D   1    False  False
    E   2     True   True
    

    虽然这给了我想要的东西,但我无法在loc选择操作中选择评估为True的行:

    data_set_2.loc[~data_set_2[["id1","id2"]].isin(data_set_1)]
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
      File "/usr/local/bfm/lib/python/pandas/0.20.2-cp35/pandas/core/indexing.py", line 1328, in __getitem__
        return self._getitem_axis(key, axis=0)
      File "/usr/local/bfm/lib/python/pandas/0.20.2-cp35/pandas/core/indexing.py", line 1539, in _getitem_axis
        raise ValueError('Cannot index with multidimensional key')
    ValueError: Cannot index with multidimensional key
    

    让我觉得这不是解决问题的正确方法。关于如何最好地实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:1)

对于第一种情况,您可以使用np.setdiff1d

vals = np.setdiff1d(data_set_2.id1, data_set_1.id1)
print(vals)
array(['E', 'F'], dtype=object)

对于第二种情况,setdiff1d不起作用,但一个简单的设定差异应该足够好。

vals = set(data_set_2.iloc[:, :2].apply(tuple, 1)) \
                       -  set(data_set_1.apply(tuple, 1))
print(vals)
{('B', '1'), ('C', '1'), ('E', '2'), ('F', '2')}

或者,为了改进现有方法,您可以沿着这些方向做点什么:

m = ~data_set_2[["id1","id2"]].isin(data_set_1)

print(m[m.all(1)])
          id1   id2
id1 id2
B   1    True  True
F   2    True  True
C   1    True  True
E   2    True  True

vals = m[m.all(1)].index.tolist()

print(vals)
[('B', '1'), ('F', '2'), ('C', '1'), ('E', '2')]

答案 1 :(得分:1)

您可以尝试使用反连接来获取所需的数据。

{{1}}