基于多列创建条件标记:按连续三月completed值判定用户状态
问题:基于DataFrame的用户违约状态判定
判定规则
若某Id存在连续3个月的completed列值为0,则标记为defaulter;否则标记为non_defaulter。
输入DataFrame
Id Month Year scheduled completed A Jan 2021 0 0 A Feb 2021 1 0 A mar 2021 0 0 B June 2021 0 1 B July 2021 0 1 B Aug 2021 0 1 B Sep 2021 0 1 C Nov 2021 1 0 C Dec 2021 1 0 C Jan 2022 1 0 C Feb 2022 1 0
预期输出
Id status A defaulter B non_defaulter C defaulter
解决方案(Pandas实现)
核心步骤:先统一日期格式并按时间排序,再分组计算连续0的区间长度,最后根据长度判定状态。
代码实现:
import pandas as pd # 构造输入DataFrame df = pd.DataFrame({ 'Id': ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C'], 'Month': ['Jan', 'Feb', 'mar', 'June', 'July', 'Aug', 'Sep', 'Nov', 'Dec', 'Jan', 'Feb'], 'Year': [2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2022, 2022], 'scheduled': [0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1], 'completed': [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0] }) # 统一月份格式并转换为日期 df['Month'] = df['Month'].str.capitalize() df['date'] = pd.to_datetime(df['Month'] + ' ' + df['Year'].astype(str), format='%b %Y') # 按Id分组并按日期排序 df = df.sort_values(['Id', 'date']).reset_index(drop=True) # 标记completed=0的行,并生成连续区间分组ID df['is_zero'] = df['completed'] == 0 df['zero_group'] = df.groupby('Id')['is_zero'].apply(lambda x: x.ne(x.shift()).cumsum()) # 统计每个连续0区间的长度 zero_lengths = df[df['is_zero']].groupby(['Id', 'zero_group']).size().reset_index(name='count') # 判定每个Id的状态 status_df = zero_lengths.groupby('Id')['count'].max().reset_index() status_df['status'] = status_df['count'].apply(lambda x: 'defaulter' if x >= 3 else 'non_defaulter') # 补全无连续0的Id状态(如B) all_ids = df['Id'].unique() status_df = status_df.set_index('Id').reindex(all_ids).fillna('non_defaulter').reset_index() # 输出结果 print(status_df[['Id', 'status']])
代码说明
- 日期处理:将月份和年份合并为可排序的datetime对象,确保跨年度的连续月份(如2021年12月→2022年1月)能被正确识别。
- 连续区间标记:通过
ne(x.shift()).cumsum()生成每个连续0序列的分组ID,方便统计区间长度。 - 状态判定:取每个Id的最长连续0区间长度,≥3则标记为
defaulter;无连续0的Id直接标记为non_defaulter。
内容的提问来源于stack exchange,提问作者Roshankumar
相关产品推荐
相关产品推荐

