Pandas:基于多列日期关联条件创建住院状态新列
解决方案
我来帮你搞定这个需求!咱们需要把日期的次日关联逻辑加进去,之前的代码只完成了第一步(判断AB和CD列是否有非空数据),现在补上日期校验的部分就可以了。
核心思路
要满足你的两个判断条件,我们可以分两步走:
- 先确认AAA/BBB中至少有一个非空字典,同时CCC/DDD中至少有一个非空字典
- 把AAA/BBB里的所有日期转成datetime格式,加一天后,检查是否有任何一个转换后的日期出现在CCC/DDD的日期集合里
完整代码实现
import pandas as pd from datetime import datetime, timedelta def check_hospitalized(row): # 收集AAA和BBB中的所有日期 ab_dates = set() for col in ['AAA', 'BBB']: val = row[col] if pd.notna(val): # 排除NaN值 ab_dates.update(val.keys()) # 收集CCC和DDD中的所有日期 cd_dates = set() for col in ['CCC', 'DDD']: val = row[col] if pd.notna(val): cd_dates.update(val.keys()) # 条件1:AB和CD都有非空日期数据 if not ab_dates or not cd_dates: return 'No' # 条件2:检查是否存在AB日期的次日在CD日期中 for date_str in ab_dates: try: # 转成datetime,加一天,再转回字符串格式 next_day = (datetime.strptime(date_str, '%Y-%m-%d') + timedelta(days=1)).strftime('%Y-%m-%d') if next_day in cd_dates: return 'Yes' except ValueError: # 如果日期格式不对,跳过这个日期(根据你的数据情况可以调整) continue # 不满足条件2就返回No return 'No' # 测试你的示例数据 data = [ {'ID': 1234, 'AAA': {'2015-01-01': 1}, 'BBB': {'2016-01-01': 1, '2016-02-15': 2}, 'CCC': {'2015-01-02': 1}, 'DDD': {'2016-01-02': 1}}, {'ID': 1235, 'AAA': {'2017-11-05': 1, '2018-06-05': 1}, 'BBB': {'2018-01-05': 1}, 'CCC': pd.NA, 'DDD': {'2017-01-06': 1}}, {'ID': 1236, 'AAA': {'2017-11-05': 1, '2018-06-05': 1}, 'BBB': {'2018-01-05': 1}, 'CCC': pd.NA, 'DDD': {'2018-01-06': 1}} ] df = pd.DataFrame(data) # 生成新列 df['Hospitalized'] = df.apply(check_hospitalized, axis=1) print(df)
代码解释
- 日期收集:遍历AB和CD列,把非空字典里的日期都提取到集合中,方便后续快速查找
- 条件1校验:如果AB或CD的日期集合为空,直接返回No
- 次日校验:把每个AB日期转成datetime,加一天后转回字符串,检查是否在CD的日期集合里,只要有一个符合就返回Yes
- 异常处理:加了
try-except防止日期格式错误的情况(如果你的数据日期格式都是标准的YYYY-MM-DD,可以去掉这部分)
运行结果
运行后会得到你期望的输出:
| ID | AAA | BBB | CCC | DDD | Hospitalized |
|---|---|---|---|---|---|
| 1234 | {'2015-01-01': 1} | {'2016-01-01': 1, '2016-02-15': 2} | {'2015-01-02': 1} | {'2016-01-02': 1} | Yes |
| 1235 | {'2017-11-05': 1, '2018-06-05': 1} | {'2018-01-05': 1} | NaN | {'2017-01-06': 1} | No |
| 1236 | {'2017-11-05': 1, '2018-06-05': 1} | {'2018-01-05': 1} | NaN | {'2018-01-06': 1} | Yes |
内容的提问来源于stack exchange,提问作者Roy
相关产品推荐
相关产品推荐

