2014-01-19 33 views
4

我有一些關於銷售的數據,比如說,想看看不同的郵政編碼如何比較:做一些交付比其他交易更有利的業務嗎?所以我通過郵編分組,並且可以根據每個郵政編碼輕鬆獲取各種統計信息。但是,有一些非常高價值的工作扭曲了統計數據,所以我想要做的就是忽略異常值。出於各種原因,我想要做的是按組來定義異常值:例如,將數據框中的行放在組中最高的第x百分位或組中的前n位。使用基於組的條件放下一些熊貓數據框行

所以,如果我有以下數據幀:

>>> df 
Out[67]: 
    A   C   D 
0 foo -0.536732 0.061055 
1 bar 1.470956 1.350996 
2 foo 1.981810 0.676978 
3 bar -0.072829 0.417285 
4 foo -0.910537 -1.634047 
5 bar -0.346749 -0.127740 
6 foo 0.959957 -1.068385 
7 foo -0.640706 2.635910 

我希望能有一些功能,比如說drop_top_n(df, group_column, value_column, number_to_drop)其中drop_top_n(df, "A", "C", 2)將返回

 A   C   D 
0 foo -0.536732 0.061055 
4 foo -0.910537 -1.634047 
5 bar -0.346749 -0.127740 
7 foo -0.640706 2.635910 

使用filter滴整個羣體,而不是羣體的一部分。

我可以遍歷組,我猜想,併爲每個組找出要刪除哪些行,然後回到原始數據框並放棄它們,但這似乎非常笨拙。有沒有更好的辦法?

回答

3

您可以使用apply()方法:

import pandas as pd 
import io 


txt="""  A   C   D 
0 foo -0.536732 0.061055 
1 bar 1.470956 1.350996 
2 foo 1.981810 0.676978 
3 bar -0.072829 0.417285 
4 foo -0.910537 -1.634047 
5 bar -0.346749 -0.127740 
6 foo 0.959957 -1.068385 
7 foo -0.640706 2.635910""" 

df = pd.read_csv(io.BytesIO(txt), delim_whitespace=True, index_col=0) 

def f(df): 
    return df.sort("C").iloc[:-2] 
df2 = df.groupby("A", group_keys=False).apply(f) 
print df2 

輸出:

 A   C   D 
5 bar -0.346749 -0.127740 
4 foo -0.910537 -1.634047 
7 foo -0.640706 2.635910 
0 foo -0.536732 0.061055 

如果你想原來的順序:

print df2.reindex(df.index[df.index.isin(df2.index)]) 

輸出:

A   C   D 
0 foo -0.536732 0.061055 
4 foo -0.910537 -1.634047 
5 bar -0.346749 -0.127740 
7 foo -0.640706 2.635910 

獲得以上組平均行:

def f(df): 
    return df[df.C>df.C.mean()] 
df3 = df.groupby("A", group_keys=False).apply(f) 
print df3 
+0

我認爲這是我想要的。 apply()分別對由groupby()生成的每個組執行操作。我沒有意識到這一點。 – lpryor

7

在0.13,你可以使用cumcount

In [11]: df[df.sort('C').groupby('A').cumcount(ascending=False) >= 2] # use .sort_index() to remove UserWarning 
Out[11]: 
    A   C   D 
0 foo -0.536732 0.061055 
4 foo -0.910537 -1.634047 
5 bar -0.346749 -0.127740 
7 foo -0.640706 2.635910 

[4 rows x 3 columns] 

它可能更有意義,首先進行排序:

In [21]: df = df.sort('C') 

In [22]: df[df.groupby('A').cumcount(ascending=False) >= 2] 
Out[22]: 
    A   C   D 
4 foo -0.910537 -1.634047 
7 foo -0.640706 2.635910 
0 foo -0.536732 0.061055 
5 bar -0.346749 -0.127740 

[4 rows x 3 columns] 
+0

這很有趣,並解決我給了具體的例子很友好地。是否有一個更一般的方法來做到這一點,例如,如果我想放棄(或保留)只有那些具有高於組平均值或模式值的行?或者在最高的第x百分位數內? – lpryor

+0

@lpryor你可以做一個合適的申請只返回這些行... –

相關問題