基于Python实现按邮箱的会员积分过期日期迭代计算
按邮箱维度计算积分过期日期的Python实现
需求规则
- 默认过期日期为记录的
date_created加上366天 - 同一客户(按邮箱区分)的购买记录中,若后续新购买记录与当前购买记录的间隔≤365天,则当前记录的过期日期需更新为最后一次购买记录的过期日期
- 若两次购买间隔超过365天,则当前记录的过期日期保持默认值,不做修改
- 非购买类记录的过期日期继承最近一次购买记录的过期日期
输入数据集
data = """date_created,first_name,last_name,email,description,points_x,expire_date 20.01.2020,namex,surenamex,test@hotmail.com,Make a Purchase,74, 20.01.2022,namex,surenamex,test@hotmail.com,Double Points for Sale,148, 3.02.2022,namex,surenamex,test@hotmail.com,Make a Purchase,70, 10.02.2022,namex,surenamex,test@hotmail.com,Duplicate Campaign,-74, 23.02.2022,namex,surenamex,test@hotmail.com,Make a Purchase,0, 20.01.2020,namey,surenamey,test2@hotmail.com,Make a Purchase,74, 20.01.2022,namey,surenamey,test2@hotmail.com,Double Points for Sale,148, 3.02.2022,namey,surenamey,test2@hotmail.com,Make a Purchase,70, 10.02.2022,namey,surenamey,test2@hotmail.com,Duplicate Campaign,-74, 23.02.2022,namey,surenamey,test2@hotmail.com,Make a Purchase,0, """
修正后的完整代码
import pandas as pd # 读取数据并转换日期格式 df = pd.read_csv(pd.io.common.StringIO(data), parse_dates=['date_created'], dayfirst=True) def calculate_expire_dates(group): # 按日期排序分组内的记录 group = group.sort_values('date_created').reset_index(drop=True) # 初始化变量:记录最近一次购买的日期和对应的过期日期 last_purchase_date = None last_expire_date = None # 先处理所有购买记录,从后往前迭代更新过期日期 purchase_indices = group[group['description'] == 'Make a Purchase'].index # 从最后一条购买记录开始往前遍历 for i in reversed(purchase_indices): current_date = group.at[i, 'date_created'] # 默认过期日期 default_expire = current_date + pd.DateOffset(days=366) if i == purchase_indices[-1]: # 最后一条购买记录,过期日期用默认值 group.at[i, 'expire_date'] = default_expire last_expire_date = default_expire last_purchase_date = current_date else: # 计算当前购买与下一次购买的间隔天数 next_purchase_date = group.at[purchase_indices[purchase_indices.get_loc(i)+1], 'date_created'] days_diff = (next_purchase_date - current_date).days if days_diff <= 365: # 间隔≤365天,更新为下一次购买的过期日期 group.at[i, 'expire_date'] = last_expire_date else: # 间隔超过365天,使用默认过期日期 group.at[i, 'expire_date'] = default_expire last_expire_date = default_expire last_purchase_date = current_date # 处理非购买记录,继承最近一次购买的过期日期 for i in range(len(group)): if group.at[i, 'description'] != 'Make a Purchase': # 找到当前日期之前最近的购买记录的过期日期 prior_purchases = group[(group['description'] == 'Make a Purchase') & (group['date_created'] <= group.at[i, 'date_created'])] if not prior_purchases.empty: group.at[i, 'expire_date'] = prior_purchases.iloc[-1]['expire_date'] return group # 按邮箱分组计算过期日期 df = df.groupby('email').apply(calculate_expire_dates).reset_index(drop=True) # 格式化日期显示 df['expire_date'] = df['expire_date'].dt.strftime('%d.%m.%Y') print(df)
代码说明
- 数据读取与日期转换:使用
pd.read_csv读取字符串数据,通过parse_dates和dayfirst=True将date_created转换为datetime类型,确保日期计算正确。 - 分组处理逻辑:通过
groupby('email')按客户邮箱分组,确保每个客户的记录独立计算。 - 购买记录过期日期计算:
- 对分组内的购买记录按日期排序,从后往前迭代:最后一条购买记录使用默认过期日期;前面的购买记录如果和下一次购买间隔≤365天,就继承下一次购买的过期日期,否则使用自己的默认值。
- 这种从后往前的方式能自动将所有符合条件的历史购买记录的过期日期更新为最后一次有效购买的过期日期。
- 非购买记录处理:遍历非购买记录,找到当前日期之前最近的购买记录,继承其过期日期。
- 日期格式化:将计算后的
expire_date格式化为与原始数据一致的dd.mm.yyyy格式。
内容的提问来源于stack exchange,提问作者crawlers
相关产品推荐
相关产品推荐

