如何分组并删除包含“-inf”或 "inf" 的行以及之前的所有行
How to groupby and drop rows that include "-inf" or "inf" and all the previous rows
我有以下 df
,我想按“分组”进行分组并删除 1) 不仅包括 NaN
的行,还包括所有前面的值或 2) 最后一个之前的行NaN
.
group date value
1 jan2019 NaN
1 jan2019 3
1 jan2019 NaN
1 feb2019 3
1 mar2019 4
1 mar2019 5
2 feb2019 0
2 feb2019 NaN
2 mar2019 7
2 mar2019 4
2 apr2019 5
所需的 df 版本 1。
group date value
1 feb2019 3
1 mar2019 4
1 mar2019 5
2 mar2019 7
2 mar2019 4
2 apr2019 5
需要 df 版本 2。
group date value
1 jan2019 NaN
1 feb2019 3
1 mar2019 4
1 mar2019 5
2 feb2019 NaN
2 mar2019 7
2 mar2019 4
2 apr2019 5
您可以使用 abs
+eq
标记 inf 值。然后也标记它之前的所有值,您可以颠倒系列的顺序并使用 cummax
。既然你想跨组做这个工作,你可以使用groupby.cummax
。最后,使用布尔掩码通过 loc
:
过滤所需的输出
out = df.loc[~df['value'].abs().eq(float('inf'))[::-1].groupby(df['group']).cummax()]
如果要标记的值是 NaN(而不是 inf),那么我们可以改用 isna
:
out = df.loc[~df['value'].isna()[::-1].groupby(df['group']).cummax()]
输出:
group date value
2 1 feb2019 3.0
3 1 mar2019 4.0
4 1 mar2019 5.0
7 2 mar2019 7.0
8 2 mar2019 4.0
9 2 apr2019 5.0
对于第三个输出,可以使用groupby.shift
:
out = df.loc[(~df['value'].isna()[::-1].groupby(df['group']).cummax()).groupby(df['group']).shift().fillna(True)]
输出:
group date value
2 1 jan2019 NaN
3 1 feb2019 3.0
4 1 mar2019 4.0
5 1 mar2019 5.0
7 2 feb2019 NaN
8 2 mar2019 7.0
9 2 mar2019 4.0
10 2 apr2019 5.0
一种更冗长但可能更易读的方法。 .isin
适用于 NaN 和 infs。
def filter_preceding(df, search_values=[np.nan, np.inf, -np.inf]):
ind = np.where(df['values'].isin(search_values))[0]
if len(ind) == 0:
return df
max_ind = ind.max()
return df.iloc[max_ind + 1:, :]
df.groupby('group').apply(filter_preceding).reset_index(drop=True)
我有以下 df
,我想按“分组”进行分组并删除 1) 不仅包括 NaN
的行,还包括所有前面的值或 2) 最后一个之前的行NaN
.
group date value
1 jan2019 NaN
1 jan2019 3
1 jan2019 NaN
1 feb2019 3
1 mar2019 4
1 mar2019 5
2 feb2019 0
2 feb2019 NaN
2 mar2019 7
2 mar2019 4
2 apr2019 5
所需的 df 版本 1。
group date value
1 feb2019 3
1 mar2019 4
1 mar2019 5
2 mar2019 7
2 mar2019 4
2 apr2019 5
需要 df 版本 2。
group date value
1 jan2019 NaN
1 feb2019 3
1 mar2019 4
1 mar2019 5
2 feb2019 NaN
2 mar2019 7
2 mar2019 4
2 apr2019 5
您可以使用 abs
+eq
标记 inf 值。然后也标记它之前的所有值,您可以颠倒系列的顺序并使用 cummax
。既然你想跨组做这个工作,你可以使用groupby.cummax
。最后,使用布尔掩码通过 loc
:
out = df.loc[~df['value'].abs().eq(float('inf'))[::-1].groupby(df['group']).cummax()]
如果要标记的值是 NaN(而不是 inf),那么我们可以改用 isna
:
out = df.loc[~df['value'].isna()[::-1].groupby(df['group']).cummax()]
输出:
group date value
2 1 feb2019 3.0
3 1 mar2019 4.0
4 1 mar2019 5.0
7 2 mar2019 7.0
8 2 mar2019 4.0
9 2 apr2019 5.0
对于第三个输出,可以使用groupby.shift
:
out = df.loc[(~df['value'].isna()[::-1].groupby(df['group']).cummax()).groupby(df['group']).shift().fillna(True)]
输出:
group date value
2 1 jan2019 NaN
3 1 feb2019 3.0
4 1 mar2019 4.0
5 1 mar2019 5.0
7 2 feb2019 NaN
8 2 mar2019 7.0
9 2 mar2019 4.0
10 2 apr2019 5.0
一种更冗长但可能更易读的方法。 .isin
适用于 NaN 和 infs。
def filter_preceding(df, search_values=[np.nan, np.inf, -np.inf]):
ind = np.where(df['values'].isin(search_values))[0]
if len(ind) == 0:
return df
max_ind = ind.max()
return df.iloc[max_ind + 1:, :]
df.groupby('group').apply(filter_preceding).reset_index(drop=True)