2017-10-08 99 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

相關問題