2017-08-27 89 views
5

考慮下面的數據幀如何有條件地從熊貓數據幀

import pandas as pd 
df = pd.DataFrame({'A' : [1, 2, 3, 3, 4, 4, 5, 6, 7], 
        'B' : ['a','b','c','c','d','d','e','f','g'], 
        'Col_1' :[np.NaN, 'A','A', np.NaN, 'B', np.NaN, 'B', np.NaN, np.NaN], 
        'Col_2' :[2,2,3,3,3,3,4,4,5]}) 
df 
Out[92]: 
    A B Col_1 Col_2 
0 1 a NaN  2 
1 2 b  A  2 
2 3 c  A  3 
3 3 c NaN  3 
4 4 d  B  3 
5 4 d NaN  3 
6 5 e  B  4 
7 6 f NaN  4 
8 7 g NaN  5 

我想刪除這與關於'A' 'B'列重複的所有行刪除重複。我想刪除具有NaN條目的條目(我知道對於所有dulicates條目將會有NaN條目和非NaN條目)。最終的結果應該是這樣的

A B Col_1 Col_2 
0 1 a NaN  2 
1 2 b  A  2 
2 3 c  A  3 
4 4 d  B  3 
6 5 e  B  4 
7 6 f NaN  4 
8 7 g NaN  5 

所有高效,單行是最歡迎的

+0

在羽絨服選民的防守中,你可以選擇一個簡單的'df.drop_duplicates'給你你不想要的答案的例子。 –

+0

是的。我接受downvote :) – mortysporty

回答

3

這裏有一個選擇:

df[~((df[['A', 'B']].duplicated(keep=False)) & (df.isnull().any(axis=1)))] 
# A B Col_1 Col_2 
# 0 1 a NaN  2 
# 1 2 b  A  2 
# 2 3 c  A  3 
# 4 4 d  B  3 
# 6 5 e  B  4 
# 7 6 f NaN  4 
# 8 7 g NaN  5 

這將使用按位「非」運算符~否定滿足的是一個重複的行(參數keep=False聯合條件的行導致該方法對所有非唯一行計算爲True)並且至少包含一個空值。那麼,表達df[['A', 'B']].duplicated(keep=False)返回此係列:

# 0 False 
# 1 False 
# 2  True 
# 3  True 
# 4  True 
# 5  True 
# 6 False 
# 7 False 
# 8 False 

...和表達df.isnull().any(axis=1)返回此係列:

# 0  True 
# 1 False 
# 2 False 
# 3  True 
# 4 False 
# 5  True 
# 6 False 
# 7  True 
# 8  True 

...我們用小括號括兩個(當使用多個由熊貓語法要求在索引操作表達式),然後包起來再括號這樣我們就可以否定整個表達式(即~(...)),像這樣:

~((df[['A','B']].duplicated(keep=False)) & (df.isnull().any(axis=1))) & (df['Col_2'] != 5) 

# 0  True 
# 1  True 
# 2  True 
# 3 False 
# 4  True 
# 5 False 
# 6  True 
# 7  True 
# 8 False 

通過進一步使用邏輯運算符&|(「或」運算符),可以構建更復雜的條件。與SQL一樣,根據需要將您的條件與其他括號進行分組;例如,基於邏輯「條件X條件Y爲真,或者條件Z爲真」與df[ ((X) & (Y)) | (Z) ]進行過濾。

+0

我認爲你需要將'keep = False'傳遞給''duplicate''才能工作。 – ayhan

+0

@ayhan我只是在想同樣的事情:) – cmaher

+0

嗨。如果除了我們想要擺脫的「NaN」之外還有其他價值,這會起作用嗎?我們可以在'&'之後修改參數嗎? – mortysporty

5

如果目標是隻降NaN重複,需要一個稍微複雜的解決方案。

首先,根據ABCol_1排序,所以NaN s被移動到每個組的底部。然後調用df.drop_duplicateskeep=first

out = df.sort_values(['A', 'B', 'Col_1']).drop_duplicates(['A', 'B'], keep='first') 
print(out) 

    A B Col_1 Col_2 
0 1 a NaN  2 
1 2 b  A  2 
2 3 c  A  3 
4 4 d  B  3 
6 5 e  B  4 
7 6 f NaN  4 
8 7 g NaN  5 
+0

也許:)但這是否保證'Col_1'的非'NaN'值是保存的行? – mortysporty

+1

@mortysporty編輯。 –

+0

我在這篇文章中得到了贊成和upvote。我想我應該看看答案是多麼簡單。但你解決它比我會更快:)謝謝! – mortysporty

1

或者您也可以使用first(),通過使用第一個,將會返回第一個notnull的值,所以原始輸入的順序並不重要。

df.groupby(['A','B']).first() 

Out[180]: 
    Col_1 Col_2 
A B    
1 a NaN  2 
2 b  A  2 
3 c  A  3 
4 d  B  3 
5 e  B  4 
6 f NaN  4 
7 g NaN  5