2016-07-29 34 views
2

我有一個面板數據,我想放下每個組中包含NaN的第一行(幾行)。 (或者,其可能下降基於組和其它條件中的索引一些一般方法。)大熊貓頭幾行包含nan在每組

df = pd.DataFrame(
{'ID': [10001, 10001, 10001, 10002, 10002, 10002, 10003, 10003, 10003, 10003], 
'PRICE': [None, 11.5, 14.31, 15.125, 14.44, None, None, None, None, 23.55], 
'date': [19920103, 19920106, 19920107, 19920108, 19920109, 19920110, 
      19920113, 19920114, 19920115, 19920116]}, 
index = range(1,11)) 

的數據將如下所示:

ID  PRICE date 
1 10001 NaN  19920103 
2 10001 11.500 19920106 
3 10001 14.310 19920107 
4 10002 15.125 19920108 
5 10002 14.440 19920109 
6 10002 NaN  19920110 
7 10003 NaN  19920113 
8 10003 NaN  19920114 
9 10003 NaN  19920115 
10 10003 23.550 19920116 

我想下降線1和7,但不是行9中,由於線9是不是第幾個丟失的觀測之一,我試圖

def mask_first_missing(x): 
    result = x.notnull() & x.rank()==1 
    return result 

mask = df.groupby(['ID'])['PRICE'].transform(mask_first_missing).astype(bool) 
print(df[mask]) 

但除去行1,7和9,顯然行9沒有處於組3中的第一觀察,

如果我這樣做

df[df.groupby('ID', as_index=False)['PRICE'].nth(0).notnull()] 

然後根據groupby對象創建的索引不會與原來的數據框對齊

任何人可以幫助我?謝謝

+1

是什麼定義規則NaN的保留和下降? – piRSquared

回答

0

謝謝你爲你提供幫助,但我認爲這兩個答案都不符合我的任務。

我自己想出了一個解決方案,通過創建子索引列。

df = pd.DataFrame(
{'ID': [10001, 10001, 10001, 10001, 10002, 10002, 10002, 10003, 10003, 10003, 10003], 
'PRICE': [None, 11.5, None, 14.31, 15.125, 14.44, None, None, None, None, 23.55], 
'date': [19920103, 19920106, 19920107, 19920108, 19920109, 19920110, 
      19920113, 19920114, 19920115, 19920116, 19920122]}, 
index = range(1,12)) 

df.loc[:, 'subindex'] = df.groupby('ID').cumcount() 

然後一會取得

ID  PRICE date subindex 
1 10001 NaN  19920103 0 
2 10001 11.500 19920106 1 
3 10001 NaN  19920107 2 
4 10001 14.310 19920108 3 
5 10002 15.125 19920109 0 
6 10002 14.440 19920110 1 
7 10002 NaN  19920113 2 
8 10003 NaN  19920114 0 
9 10003 NaN  19920115 1 
10 10003 NaN  19920116 2 
11 10003 23.550 19920122 3 

而是基於GROUPBY做的一切,現在我可以選擇基於列的「子索引」每個組的第n觀察。

現在,如果我想刪除每個組的「價格」的前兩個NaN的觀察,我可以創造一個面具

mask_first_few_nan = (df.loc[:, 'PRICE'].isnull()) & (df.loc[:, 'subindex'] <= 1) 
df[~mask_first_few_nan] 

結果是

ID  PRICE date subindex 
2 10001 11.500 19920106 1 
3 10001 NaN  19920107 2 
4 10001 14.310 19920108 3 
5 10002 15.125 19920109 0 
6 10002 14.440 19920110 1 
7 10002 NaN  19920113 2 
10 10003 NaN  19920116 2 
11 10003 23.550 19920122 3 
1

這是一個辦法做到這一點:使用自定義排名

notnull = df.PRICE.notnull() 
protected = df.index > df.PRICE.last_valid_index() 

df[notnull | protected] 

enter image description here

+0

非常感謝您,但我有一個小組,我想刪除每個小組的前幾個缺失觀察結果。這裏的方法不起作用。也許這是我的錯,我應該讓我的問題更清楚 – GrumpyJun

+0

我更新了示例數據,我嘗試了這種方法,但效果不佳 – GrumpyJun

0

alternatve方法:

In [49]: %paste 
df[df.assign(x=np.where(pd.isnull(df.PRICE), 1, np.nan)) 
    .groupby('ID').x.cumsum().fillna(np.inf) > 1 
] 
## -- End pasted text -- 
Out[49]: 
     ID PRICE  date 
2 10001 11.500 19920106 
3 10001 14.310 19920107 
4 10002 15.125 19920108 
5 10002 14.440 19920109 
6 10002 14.120 19920110 
8 10003 16.500 19920114 
9 10003  NaN 19920115 

說明:

In [50]: df.assign(x=np.where(pd.isnull(df.PRICE), 1, np.nan)) 
Out[50]: 
     ID PRICE  date x 
1 10001  NaN 19920103 1.0 
2 10001 11.500 19920106 NaN 
3 10001 14.310 19920107 NaN 
4 10002 15.125 19920108 NaN 
5 10002 14.440 19920109 NaN 
6 10002 14.120 19920110 NaN 
7 10003  NaN 19920113 1.0 
8 10003 16.500 19920114 NaN 
9 10003  NaN 19920115 1.0 

In [51]: df.assign(x=np.where(pd.isnull(df.PRICE), 1, np.nan)).groupby('ID').x.cumsum().fillna(np.inf) 
Out[51]: 
1 1.000000 
2   inf 
3   inf 
4   inf 
5   inf 
6   inf 
7 1.000000 
8   inf 
9 2.000000 
Name: x, dtype: float64 

In [52]: df.assign(x=np.where(pd.isnull(df.PRICE), 1, np.nan)).groupby('ID').x.cumsum().fillna(np.inf) > 1 
Out[52]: 
1 False 
2  True 
3  True 
4  True 
5  True 
6  True 
7 False 
8  True 
9  True 
Name: x, dtype: bool