如何在Python DataFrame中判定生产日期所属的日期区间
解决Python DataFrame中为ID匹配生产日期区间左边界日期列的问题
前提准备
首先确保所有日期列(包括「生产日期」)都转换为datetime类型,避免字符串比较导致的错误:
import pandas as pd # 构造示例DataFrame(模拟稀疏日期列场景) data = { 'ID': ['aa', 'bb', 'cc'], '生产日期': ['6/18/2022', '5/20/2022', '9/10/2022'], 'date6': ['5/10/2022', '5/15/2022', pd.NA], 'date7': ['7/20/2022', '5/25/2022', '9/5/2022'], 'date13': ['6/15/2022', pd.NA, '8/30/2022'], 'date17': ['8/29/2022', pd.NA, '9/15/2022'] } df = pd.DataFrame(data) # 转换日期类型 date_cols = [col for col in df.columns if col not in ['ID', '生产日期']] df['生产日期'] = pd.to_datetime(df['生产日期']) for col in date_cols: df[col] = pd.to_datetime(df[col])
方法一:逐行处理(适合小数据集)
定义函数提取每个ID的非NaN日期对,排序后找到符合条件的左边界列名:
def get_left_bound(row): prod_date = row['生产日期'] # 收集当前ID下所有非空的日期列与对应日期值 valid_dates = [(col, row[col]) for col in date_cols if pd.notna(row[col])] if not valid_dates: return pd.NA # 无有效日期时返回空值 # 按日期从小到大排序 valid_dates.sort(key=lambda x: x[1]) # 找到小于等于生产日期的最大日期对应的列名 left_col = None for col, dt in valid_dates: if dt <= prod_date: left_col = col else: break # 排序后后续日期更大,无需继续遍历 return left_col # 应用函数到每一行 df['标记列'] = df.apply(get_left_bound, axis=1)
方法二:矢量化操作(适合大数据集)
通过melt转长格式+分组聚合,避免逐行循环的性能瓶颈:
# 将宽表转长表,保留ID、生产日期,拆分日期列与对应值 melted_df = df.melt( id_vars=['ID', '生产日期'], value_vars=date_cols, var_name='日期列', value_name='日期值' ) # 过滤空值与大于生产日期的日期 filtered = melted_df.dropna(subset=['日期值']) filtered = filtered[filtered['日期值'] <= filtered['生产日期']] # 按ID分组,找到每个ID下最大日期对应的列名 result = filtered.groupby('ID').apply( lambda x: x.loc[x['日期值'].idxmax(), '日期列'] ).reset_index(name='标记列') # 合并回原DataFrame df = df.merge(result, on='ID', how='left')
关键说明
- 两种方法都保留了原DataFrame的所有列,未删除含NaN的列。
- 若某个ID没有任何小于等于生产日期的有效日期,
标记列会返回NaN,可根据需求补充逻辑处理这种情况。 - 日期列无需预先排序,代码内部会对每个ID的有效日期进行排序处理。
内容的提问来源于stack exchange,提问作者April
相关产品推荐
相关产品推荐

