熊猫:根据条件删除每组的行

时间:2019-02-18 17:23:21

标签: python pandas dataframe pandas-groupby

假设我具有以下数据框:

df = pd.DataFrame({"id": [1, 1, 1, 2, 2, 2], "date": [pd.Timestamp(2016, 7, 29), pd.Timestamp(2017, 8, 22), pd.Timestamp(2017, 10, 9), pd.Timestamp(2018, 1, 9), pd.Timestamp(2018, 3, 31), pd.Timestamp(2018, 7, 5)], "other_col": [11.1, 77.7, 22.2, 33.3, 44.4, 88.8]})

我想要实现的是删除每个组的最后N行,其中data-frame is grouped by idN为:具有date的行数位于最后一行date的3个月内(这将删除最后一行)。结果数据框应为:

r_df = pd.DataFrame({"id": [1, 2, 2], "date": [pd.Timestamp(2016, 7, 29), pd.Timestamp(2018, 1, 9), pd.Timestamp(2018, 3, 31)], "other_col": [11.1, 33.3, 44.4]})
  • 数据框的行将始终排序
  • 还应删除最后一行,因为默认情况下,其日期在每个组的“删除”日期范围内。

2 个答案:

答案 0 :(得分:1)

单个基于日期的lambda函数可以解决此问题。甚至不关心对行进行排序。

df.groupby('id').apply(
  lambda x: x.loc[
    x.date < (x.date.max() - pd.Timedelta(3, unit='M'))
  ]
).reset_index(drop=True)

更新

正如@jpp所指出的,以下选择要快得多(约12倍):

df[df['date'] < (df.groupby('id')['date'].transform('max') - pd.Timedelta(3, unit='M'))]

作为额外的奖励,它还保留了原始顺序和索引。

答案 1 :(得分:0)

def remove_n_row(grouped_df):
  last_row_date = grouped_df.iloc[-1]['date']
  grouped_df_filtered = grouped_df[(grouped_df['date'] <=last_row_date) & (grouped_df['date'] <=last_row_date - timedelta(days=90))]
  return grouped_df_filtered

from datetime import timedelta
r_df = df.groupby('id').apply(remove_n_row).reset_index(drop=True)
print(r_df)

输出

    id     date     other_col
0   1   2016-07-29   11.1
1   2   2018-01-09   33.3
2   2   2018-03-31   44.4