Pandas按组使用第一个有效指数下降nan

w8rqjzmb  于 2022-12-16  发布在  其他
关注(0)|答案(3)|浏览(133)

我正在使用以下DataFrame:

Date    Id    Amount
   0    201301    1      nan
   1    201302    1      nan
   2    201303    1      100
   3    201304    1      120
   4    201305    1      nan
   5    201306    1      120
   6    201302    2      nan
   7    201303    2      150
   8    201304    2      180

我试图通过Id得到Amount的第一个有效索引,但由于某些原因,这不起作用:

df.groupby('Id').Amount.first_valid_index()

我也在尝试这个:

df.groupby('Id').Amount.apply(lambda x: x.first_valid_index())

但我的数据集是20M+行,所以它需要太长的时间,这对我来说不起作用。
有没有更快的方法按组查找第一个索引?
我期望的输出是:

first_idx = [2,7]

或者更好:

Date    Id    Amount

   2    201303    1      100
   3    201304    1      120
   4    201305    1      nan
   5    201306    1      120
   7    201303    2      150
   8    201304    2      180

编辑:df.groupby('Id').Amount.apply(lambda x: x.first_valid_index())确实有效,但我觉得必须有一个更快的选择,问题似乎并不复杂。

juzqafwq

juzqafwq1#

**选项1:**仅获取前几个索引:

df[df.Amount.notna()].groupby('Id').Date.idxmin()
# 1.42 ms ± 14.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

产出:

Id
1    2
2    7
Name: Date, dtype: int64

**选项2:**要获取其他行,请对notna()使用cumsum

df[df['Amount'].notna().groupby(df['Id']).cumsum().gt(0)]
# 2.09 ms ± 220 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

**选项3:**您可以在组内ffill(),并选择未填充的:

df[df.groupby('Id').Amount.ffill().notna()]
# 831 µs ± 14.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

输出:

Date  Id  Amount
2  201303   1   100.0
3  201304   1   120.0
4  201305   1     NaN
5  201306   1   120.0
7  201303   2   150.0
8  201304   2   180.0

结论:选项3最快!
**更新:**使用选项3过滤两端:

amt_group = df.groupby('Id').Amount
df[amt_group.bfill().notna() & amt_group.ffill().notna()]
relj7zay

relj7zay2#

.notnull + .cumsum创建一个掩码,以获取组中第一个非空Amount之后的所有内容,然后创建一个切片。

m = df.Amount.notnull().groupby(df.Id).cumsum().ge(1)

df.loc[m]
     Date  Id  Amount
2  201303   1   100.0
3  201304   1   120.0
4  201305   1     NaN
5  201306   1   120.0
7  201303   2   150.0
8  201304   2   180.0
u0njafvf

u0njafvf3#

如果还需要移位(例如,从第一个有效索引之前的索引开始),使用ffill()和shift()作为链式调用将移位帧而不是组。

ffilled = df['Amount'].groupby('Id').ffill()
df[ffilled.groupby('Id').shift(-1, fill_value=True).notna()]

相关问题