熊猫掉落前几行每组包含纳米

时间:2016-07-29 23:16:08

标签: python pandas panel

我有一个面板数据,我想删除每组中包含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对象创建的索引与原始数据框

不对齐

有人可以帮我这个吗?谢谢

3 个答案:

答案 0 :(得分:1)

这是一种方法:

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

df[notnull | protected]

enter image description here

答案 1 :(得分:0)

使用自定义排名的替代方法:

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

答案 2 :(得分: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

现在我可以根据列'subindex'选择每组的第n次观察,而不是在基于groupby的所有事情上做。

现在,如果我想放弃每组的'PRICE'的前两个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