2017-10-08 102 views
0

我对熊猫还比较陌生,希望得到一些关于如何以最佳方式解决问题的反馈。我试图评估来自两个不同长度数据帧的两列值,以找到两种情况:比较不同长度的两个数据帧的行

  1. data_set_2中的id1不存在于data_set_1中。
  2. (id1,id2)data_set_2中的组合不存在于data_set_1中。

复杂性的一点是,我想避免使用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))] 

(这是我不知道这是最好的方式) - 获取id1,id2组合不存在于data_se中t_1:

我尝试了一个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 

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

回答

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')] 
+0

给我一点时间@COLDSPEED,试图找出如何一切,设置这里都有了用武之地 - 会尽快给您 – user3166881

+0

@ user3166881您当前的做法是快,我敢说有合并非常有竞争力。 –

+0

@ user3166881如果您的问题得到解答,请告诉我。 –

1

你可以尝试使用反连接得到你想要的数据。

import pandas as pd 
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"]}) 

# Merging two data frame on id1, then filtering base on indicator 
data_result_1 = data_set_2.merge(data_set_1.loc[:, ["id1"]], on="id1", how="outer", indicator=True) 
data_result_1 = data_result_1[data_result_1['_merge'] == 'left_only'] 

# Merging two data frame on id1 and id2, then filtering base on indicator 
data_result_2 = data_set_2.merge(data_set_1.loc[:, ["id1", "id2"]], on=["id1", "id2"], how="outer", indicator=True) 
data_result_2 = data_result_2[data_result_2['_merge'] == 'left_only'] 


print([tuple(x) for x in data_result_1.loc[:, ["id1"]].values]) 
print([tuple(x) for x in data_result_2.loc[:, ["id1", "id2"]].values]) 
+0

合并是一种干净的方法!没想到用指标 – user3166881

相关问题