按CODE和QUARTER分组获取PP<1连续时段起止日期及统计
问题描述
现有如下DataFrame:
DATE CODE QUARTER PP 0 1964-01-01 100007 1964Q1 NaN 1 1964-01-02 100007 1964Q1 NaN 2 1964-01-03 100007 1964Q1 NaN 3 1964-01-04 100007 1964Q1 NaN 4 1964-01-05 100007 1964Q1 NaN ... ... ... ... 10656619 2023-03-27 118004 2023Q1 0.0 10656620 2023-03-28 118004 2023Q1 0.0 10656621 2023-03-29 118004 2023Q1 0.0 10656622 2023-03-30 118004 2023Q1 0.0 10656623 2023-03-31 118004 2023Q1 0.0 [2647935 rows x 4 columns]
需求:按CODE和QUARTER分组,完成三个统计:
- PP<1的最长连续天数
- 该最长连续时段的起止日期
- 每组内PP列的总NaN数量
已编写部分代码计算最长连续天数:
df['CONDITION']=(df['PP']<1) #CALCULATE THE maximum value of consecutive days in which PP<1 max_values = (df.groupby(['CODE','QUARTER']) .apply(lambda g: (g['CONDITION'].ne(g['CONDITION'].shift()).cumsum() # Group continuous [g['CONDITION']] # Keep True .value_counts().max())) # Find max True .to_frame('MAX_CONSEC_VALUES').reset_index())
需要补充代码实现另外两个需求。
解决方案
可以通过扩展分组内的计算逻辑,一次性获取所有需要的统计项,具体代码如下:
步骤1:预处理日期列(确保为datetime类型)
如果DATE列当前是字符串格式,先转换为datetime:
df['DATE'] = pd.to_datetime(df['DATE'])
步骤2:扩展分组计算逻辑
替换原有的apply函数,在每个分组内同时计算最长连续段的起止日期、长度,以及NaN数量:
df['CONDITION'] = df['PP'] < 1 def process_group(g): # 生成连续段的分组键:CONDITION变化时,分组ID递增 g['GROUP_ID'] = g['CONDITION'].ne(g['CONDITION'].shift()).cumsum() # 筛选出PP<1的连续段,计算每个段的起止日期和长度 valid_segments = g[g['CONDITION']].groupby('GROUP_ID').agg( start_date=('DATE', 'min'), end_date=('DATE', 'max'), duration=('DATE', 'count') ) # 获取最长连续段的信息,若无有效段则填充NaN/0 if not valid_segments.empty: longest_segment = valid_segments[valid_segments['duration'] == valid_segments['duration'].max()].iloc[0] max_duration = longest_segment['duration'] start_date = longest_segment['start_date'] end_date = longest_segment['end_date'] else: max_duration = 0 start_date = pd.NaT end_date = pd.NaT # 统计当前分组的NaN数量 nan_count = g['PP'].isna().sum() return pd.Series({ 'MAX_CONSEC_VALUES': max_duration, 'START_DATE': start_date, 'END_DATE': end_date, 'TOTAL_NAN': nan_count }) # 分组计算并整理结果 result = df.groupby(['CODE', 'QUARTER']).apply(process_group).reset_index()
代码说明
GROUP_ID列用于标识连续的符合条件(PP<1)的时段,每次CONDITION值变化时,ID自动递增- 对每个有效连续段,通过
agg计算起止日期和持续天数 - 筛选出持续天数最大的段,若没有有效段(比如分组内全是PP>=1或全NaN),则起止日期设为
pd.NaT,持续天数为0 - 直接用
isna().sum()统计分组内PP列的NaN总数
最终的resultDataFrame会包含CODE、QUARTER、MAX_CONSEC_VALUES、START_DATE、END_DATE、TOTAL_NAN这几列,满足所有需求。
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

