基于分组与时间约束的奶牛跛行Life_xLame计数异常问题
问题排查与修正方案
问题根源
单泌乳期的NID(如52316、35724)所有跛行记录归属同一泌乳期,原有Life_xLame计算逻辑基于全局NID的跛行时间序列做间隔判断,而非针对每个RxDate单独筛选早于该日期的跛行记录后再统计。这导致同一NID的多个RxDate复用全局间隔计算结果,无法重置计数;而多泌乳期NID因泌乳期分割,每个RxDate对应的跛行记录子集独立,计数逻辑自然生效。
修正方案
针对每个(NID, RxDate)组合,独立筛选早于该日期的跛行记录,从头统计间隔超7天的病例数,确保每个RxDate的计数独立计算。
代码实现
import pandas as pd # 确保日期字段为datetime类型 df['RxDate'] = pd.to_datetime(df['RxDate']) df['LameDate'] = pd.to_datetime(df['LameDate']) # 定义函数:针对单个(NID, RxDate)组,计算符合条件的跛行病例数 def calculate_life_lame(group): current_rx = group['RxDate'].iloc[0] # 筛选早于当前RxDate的跛行记录,按时间排序 valid_lames = group[group['LameDate'] < current_rx].sort_values('LameDate') if valid_lames.empty: return 0 # 统计间隔>7天的病例数(第一个病例默认计入) count = 1 last_lame_date = valid_lames['LameDate'].iloc[0] for date in valid_lames['LameDate'].iloc[1:]: if (date - last_lame_date).days > 7: count += 1 last_lame_date = date return count # 计算Life_xLame:按NID+RxDate分组应用函数 df['Life_xLame'] = df.groupby(['NID', 'RxDate']).apply(calculate_life_lame).reset_index(level=[0,1], drop=True) # 保留原正确的Lact_xLame计算逻辑 df['Lact_Lag'] = df.groupby(['NID', 'Lactation'])['LameDate'].diff().dt.days df['Lact_xLame'] = df.groupby(['NID', 'Lactation', 'RxDate']).apply( lambda x: (x['Lact_Lag'].isna() | (x['Lact_Lag'] > 7)).cumsum().max() ).reset_index(level=[0,1,2], drop=True)
特殊场景适配(如需重置计数)
若需求是每个RxDate仅统计上一个RxDate之后到当前RxDate之间的符合条件病例数,可使用以下函数实现计数重置:
def calculate_life_lame_reset(group): # 对当前NID的RxDate按时间排序 sorted_group = group.sort_values('RxDate').reset_index(drop=True) counts = [] last_rx = None last_valid_lame = None for idx, row in sorted_group.iterrows(): current_rx = row['RxDate'] # 筛选时间范围:上一个RxDate之后,当前RxDate之前 if last_rx: valid_lames = group[(group['LameDate'] > last_rx) & (group['LameDate'] < current_rx)].sort_values('LameDate') else: valid_lames = group[group['LameDate'] < current_rx].sort_values('LameDate') # 统计间隔>7天的病例数 cnt = 0 temp_last = last_valid_lame for date in valid_lames['LameDate']: if temp_last is None or (date - temp_last).days > 7: cnt += 1 temp_last = date counts.append(cnt) last_rx = current_rx last_valid_lame = temp_last sorted_group['Life_xLame'] = counts return sorted_group # 应用重置逻辑 df = df.groupby('NID').apply(calculate_life_lame_reset).reset_index(drop=True)
内容的提问来源于stack exchange,提问作者JohnH
相关产品推荐
相关产品推荐

