基于日期与字符变量条件设置标识字段的技术实现问询
问题描述
原始数据集:
ID Start End Place 0001 13JAN2015 20JAN2015 HospA 0001 21JAN2015 31DEC2015 HospA 0001 01JAN2018 31DEC2018 HospB 0001 01JAN2019 31DEC2019 HospA 0002 01JAN2015 31DEC2015 HospA 0002 01JAN2019 31OCT2019 HospA 0002 01NOV2019 31DEC2020 HospA ..... ........ ......... .....
需要为数据添加StartFlag和EndFlag列,规则如下:
- 针对每个ID,若时段连续且Place相同,仅在该时段首个Start日期对应的StartFlag列填“1”,其余StartFlag与EndFlag填“0”;
- 同一ID出现年份断层且Place变更时,在对应Start日期的StartFlag列填“1”,EndFlag填“0”;
- 同一ID出现年份断层但Place未变更时,在该序列首个Start日期的StartFlag列填“1”,断层前最后一行的EndFlag填“9”,断层后首个时段的StartFlag填“9”。
尝试用if语句实现,但不知道如何调用每个ID、Place对应连续/非连续时段的首个日期,期望得到解决方案。
期望输出:
ID Start End Place StartFlag EndFlag 0001 13JAN2015 20JAN2015 HospA 1 0 0001 21JAN2015 31DEC2015 HospA 0 0 0001 01JAN2018 31DEC2018 HospB 1 0 0001 01JAN2019 31DEC2019 HospA 1 0 0002 01JAN2015 30SEP2015 HospA 1 0 0002 01OCT2015 31DEC2015 HospA 0 9 0002 01JAN2019 31OCT2019 HospA 9 0 0002 01NOV2019 31DEC2020 HospA 0 0 ..... ........ ......... .....
解决方案
用Python的pandas库可以高效处理这类分组和日期连续性判断的问题,步骤如下:
1. 导入库并读取数据
import pandas as pd # 构造示例数据,实际场景可从文件读取 data = pd.DataFrame({ 'ID': ['0001', '0001', '0001', '0001', '0002', '0002', '0002'], 'Start': ['13JAN2015', '21JAN2015', '01JAN2018', '01JAN2019', '01JAN2015', '01JAN2019', '01NOV2019'], 'End': ['20JAN2015', '31DEC2015', '31DEC2018', '31DEC2019', '31DEC2015', '31OCT2019', '31DEC2020'], 'Place': ['HospA', 'HospA', 'HospB', 'HospA', 'HospA', 'HospA', 'HospA'] })
2. 转换日期格式为datetime类型
这一步是为了方便后续的日期连续性判断:
data['Start'] = pd.to_datetime(data['Start'], format='%d%b%Y') data['End'] = pd.to_datetime(data['End'], format='%d%b%Y')
3. 按ID分组处理Flag逻辑
先按ID和Start日期排序,确保时序正确,再遍历每个ID分组,根据规则设置Flag:
# 按ID和Start日期排序,保证数据时序正确 data = data.sort_values(['ID', 'Start']).reset_index(drop=True) # 初始化Flag列 data['StartFlag'] = '0' data['EndFlag'] = '0' # 遍历每个ID分组 for _, group in data.groupby('ID'): group_indices = group.index # 设置该ID首个时段的StartFlag为1 data.loc[group_indices[0], 'StartFlag'] = '1' for i in range(1, len(group_indices)): prev_idx = group_indices[i-1] curr_idx = group_indices[i] # 判断时段是否连续:上一行的End+1天等于当前行的Start is_continuous = (data.loc[prev_idx, 'End'] + pd.Timedelta(days=1)) == data.loc[curr_idx, 'Start'] same_place = data.loc[prev_idx, 'Place'] == data.loc[curr_idx, 'Place'] if is_continuous and same_place: # 时段连续且Place相同,保持默认0 continue else: if not same_place: # Place变更,当前行StartFlag设为1 data.loc[curr_idx, 'StartFlag'] = '1' else: # 年份断层且Place未变更,上一行EndFlag设为9,当前行StartFlag设为9 data.loc[prev_idx, 'EndFlag'] = '9' data.loc[curr_idx, 'StartFlag'] = '9'
4. 恢复原始日期格式(可选)
如果需要将日期转换回原始的字符串样式:
data['Start'] = data['Start'].dt.strftime('%d%b%Y').str.upper() data['End'] = data['End'].dt.strftime('%d%b%Y').str.upper()
执行完上述代码后,得到的DataFrame就符合期望输出的格式。
内容的提问来源于stack exchange,提问作者NewUsr
相关产品推荐
相关产品推荐

