2013-07-30 159 views
4

使用Python 3.3和Pandas 0.10熊貓:使用groupby和函數的數據框篩選

我有一個通過連接多個CSV文件構建的DataFrame。首先,我過濾掉名稱列中包含特定字符串的所有值。結果看起來是這樣的(簡稱爲簡潔的緣故,其實有更多列):

Name ID 
'A'  1 
'B'  2 
'C'  3 
'C'  3 
'E'  4 
'F'  4 
...  ... 

現在我的問題是,我想刪除「複製」值的特殊情況。我想刪除映射到此ID的相應名稱值爲而非類似的所有ID副本(實際上是整行)。在上面的示例中,我想保留具有ID 1,2和3的行。其中ID = 4的名稱值不相等,我想刪除這些行。

我試着用下面這行代碼(根據這裏的建議:Python Pandas: remove entries based on the number of occurrences)。

代碼:

df[df.groupby('ID').apply(lambda g: len({x for x in g['Name']})) == 1] 

不過是給我的錯誤: ValueError: Item wrong length 51906 instead of 109565!

編輯:

而不是使用apply()我一直在使用transform()也嘗試過,但是這給我的錯誤: AttributeError: 'int' object has no attribute 'ndim'。非常感謝爲什麼每個功能的錯誤是不同的解釋!

另外,我想在上面的例子中保持ID = 3的所有行。

由於提前, Matthijs

回答

5

而是長len的,我覺得你要考慮各組名稱的唯一值的數量。使用nunique(),並檢查出這個整潔的配方過濾組。

df[df.groupby('ID').Name.transform(lambda x: x.nunique() == 1).astype('bool')] 

如果升級到大熊貓0.12,您可以使用組新filter方法,這使得這個更加簡潔明瞭。

df.groupby('ID').filter(lambda x: x.Name.nunique() == 1) 

一般性發言:當然有時候,你想知道組的長度,但我發現,sizelen一個更安全的選擇,這很麻煩,我在某些情況下。

+0

我總是忘記變換! :) –

+0

哈哈。人們通常不會發現它 - 我想我至少每週回答一次轉換問題。 –

+0

我以前似乎有過幾次:)但我仍然忘記了...... –

0

你可以先刪除重複項:

In [11]: df = df.drop_duplicates() 

In [12]: df 
Out[12]: 
    Name ID 
0 A 1 
1 B 2 
2 C 3 
4 E 4 
5 F 4 

groupby ID和只考慮那些具有一個元素:

In [13]: g = df.groupby('ID') 

In [14]: size = (g.size() == 1) 

In [15]: size 
Out[15]: 
ID 
1  True 
2  True 
3  True 
4  False 
dtype: bool 

In [16]: size[size].index 
Out[16]: Int64Index([1, 2, 3], dtype=int64) 

In [17]: df['ID'].isin(size[size].index) 
Out[17]: 
0  True 
1  True 
2  True 
4 False 
5 False 
Name: ID, dtype: bool 

和布爾索引此:

In [18]: df[df['ID'].isin(size[size].index)] 
Out[18]: 
    Name ID 
0 A 1 
1 B 2 
2 C 3 
+0

謝謝你的幫助安迪,但我會與丹的答案一起去。 – Matthijs

+0

@Matthijs它更好:) –