如何在Pandas中按用户分组生成符合特定历史条件的drop列
实现按用户标记
drop列的解决方案 要完成这个需求,我们可以借助pandas的分组和累积操作高效实现。核心思路是:按user_id分组后,跟踪该用户是否出现过不符合要求的months_from_previous_purchase值,一旦出现,后续所有行的drop列都标记为1,否则保持0。
具体步骤与代码实现
假设你的数据集已经加载为pandas的DataFrame(命名为df),可以按以下步骤操作:
- 导入必要库
import pandas as pd import numpy as np
- 构造示例数据集(如果还未加载)
data = { 'user_id': ['u1', 'u1', 'u1', 'u1', 'u2', 'u2', 'u2', 'u2', 'u3', 'u3'], 'purchase_date': ['2020-06-01', '2020-07-01', '2020-08-01', '2020-09-01', '2020-06-01', '2020-08-01', '2020-08-01', '2020-09-01', '2020-06-01', '2020-07-01'], 'previous_purchase': [pd.NaT, '2020-06-01', '2020-07-01', '2020-08-01', pd.NaT, '2020-06-01', '2020-08-01', '2020-08-01', pd.NaT, '2020-06-01'], 'months_from_previous_purchase': [np.nan, 1, 1, 1, np.nan, 2, 0, 1, np.nan, 1] } df = pd.DataFrame(data) # 转换日期列类型 df['purchase_date'] = pd.to_datetime(df['purchase_date']) df['previous_purchase'] = pd.to_datetime(df['previous_purchase'])
- 标记无效行并生成
drop列
# 第一步:标记哪些行的months_from_previous_purchase不符合要求(非NaN且不是0/1) df['invalid'] = df['months_from_previous_purchase'].notna() & ~df['months_from_previous_purchase'].isin([0, 1]) # 第二步:按用户分组,用累积最大值(cummax)跟踪是否出现过无效行,再转成0/1 df['drop'] = df.groupby('user_id')['invalid'].cummax().astype(int) # 可以删除中间的invalid列(如果不需要) df = df.drop('invalid', axis=1)
代码解释
invalid列:判断当前行的months_from_previous_purchase是否是无效值——即不是NaN,同时也不是0或1。这样能精准定位用户出现不符合规则的行。- 分组累积操作
cummax():对每个用户的invalid列执行累积最大值操作,布尔值的cummax()特性是:只要出现过True(无效行),后续所有行都会保持True,完美实现“一旦用户出现过无效值,后续所有行drop为1”的要求。 astype(int):将布尔值转换为0/1,符合需求中的drop列格式。
最终输出结果
运行上述代码后,你会得到和预期完全一致的数据集:
| user_id | purchase_date | previous_purchase | months_from_previous_purchase | drop |
|---|---|---|---|---|
| u1 | 2020-06-01 | NaT | NaN | 0 |
| u1 | 2020-07-01 | 2020-06-01 | 1.0 | 0 |
| u1 | 2020-08-01 | 2020-07-01 | 1.0 | 0 |
| u1 | 2020-09-01 | 2020-08-01 | 1.0 | 0 |
| u2 | 2020-06-01 | NaT | NaN | 0 |
| u2 | 2020-08-01 | 2020-06-01 | 2.0 | 1 |
| u2 | 2020-08-01 | 2020-08-01 | 0.0 | 1 |
| u2 | 2020-09-01 | 2020-08-01 | 1.0 | 1 |
| u3 | 2020-06-01 | NaT | NaN | 0 |
| u3 | 2020-07-01 | 2020-06-01 | 1.0 | 0 |
内容的提问来源于stack exchange,提问作者Saeed Esmaili
相关产品推荐
相关产品推荐

