如何在DataFrame中按日期更新行或插入至最近日期后并填充列?
问题与解决方案
原始DataFrame
import pandas as pd df = pd.DataFrame({ 'date': ['2022-10-07 04:00:00', '2022-10-08 04:00:00'], 'col1': ['x', 'y'], 'col2': ['x1', 'x2'] }) # 务必先将date列转为datetime类型,确保日期比较和排序正常 df['date'] = pd.to_datetime(df['date'])
需求说明
- 若指定日期已存在于DataFrame中,用传入的字典数据更新该行对应列
- 若指定日期不存在,将新行插入到最近的前序日期的下一行(保证date列有序)
- 插入/更新时仅提供
col1数据,col2需从前一行填充(类似ffill逻辑)
示例效果
传入日期2022-10-07 05:00:00和字典{'col1':'z'},期望结果:
date col1 col2 0 2022-10-07 04:00:00 x x1 1 2022-10-07 05:00:00 z x1 2 2022-10-08 04:00:00 y x2
当前代码的问题
原代码会将新行添加到DataFrame末尾,无法保证date列的有序性;同时未处理col2的前向填充逻辑。
修正后的实现代码
def write(date, dic): # 统一转换为datetime类型,避免字符串比较误差 target_date = pd.to_datetime(date) # 检查目标日期是否已存在 exists_mask = df['date'] == target_date if exists_mask.any(): # 更新指定列,其他列保持不变 df.loc[exists_mask, dic.keys()] = list(dic.values()) else: # 找到插入位置:第一个大于目标日期的行索引,保证插入后date有序 insert_pos = df['date'].searchsorted(target_date) # 构建新行,初始化所有列 new_row = pd.Series(index=df.columns) new_row['date'] = target_date # 应用传入的字典数据 new_row.update(dic) # 前向填充缺失列:取前一行的数据(如果不是插入到最开头) if insert_pos > 0: new_row = new_row.fillna(df.iloc[insert_pos - 1]) # 拼接插入新行,重置索引保证连续 global df df = pd.concat([ df.iloc[:insert_pos], new_row.to_frame().T, df.iloc[insert_pos:] ], ignore_index=True)
代码说明
- 日期类型统一:将输入日期和DataFrame的date列都转为datetime,避免字符串格式导致的比较错误
- 日期存在时的更新:直接通过
loc定位目标行,仅更新字典指定的列,其余列不受影响 - 日期不存在时的插入:
- 用
searchsorted快速找到正确的插入位置,确保date列始终有序 - 创建新行后,用前一行的数据填充未指定的列(如col2),实现ffill效果
- 通过
pd.concat完成插入操作,避免索引混乱,最后重置索引
- 用
测试验证
# 调用函数插入新行 write('2022-10-07 05:00:00', {'col1': 'z'}) print(df) # 调用函数更新已有日期 write('2022-10-07 04:00:00', {'col1': 'new_x'}) print(df)
内容的提问来源于stack exchange,提问作者gotiredofcoding
相关产品推荐
相关产品推荐

