Pandas DataFrame如何将for循环逐时计算的距降雨小时数存入新列
逐行计算距上次降雨时长的实现方法
核心问题原因
你之前代码的核心问题是没有逐行存储每一步的计算结果:
- 循环过程中你只维护了单个计数器变量,没有把每次循环得到的瞬时值收集成和DataFrame行数匹配的序列
- 后续尝试的拼接、赋值操作存在结构不匹配:
df.append()需要接收同结构的DataFrame/Series对象,传入单个数值无法生成正确的逐行序列 - 直接把最终的计数器值赋给新列,只会将单个值重复填满整列,无法实现逐行记录的效果
方法1:适配你现有循环逻辑的修正方案
只需要新增一个空列表逐行收集计算结果,循环完成后直接将列表赋值给新列即可:
# 初始化小时计数器 hours_since_rainfall = 0 # 新建空列表,逐行存储每次计算的结果 calc_records = [] for rain_val in df['rain']: if rain_val == 0: hours_since_rainfall += 1 else: hours_since_rainfall = 0 # 每完成一次计算,将结果存入列表 calc_records.append(hours_since_rainfall) # 循环结束后,整体赋值给DataFrame新列 df['hours_since_rain'] = calc_records
这个方法完全保留你原本已经验证正确的计算逻辑,只补充了结果存储的环节,运行后就能得到和你给出的示例完全一致的输出。
方法2:更高效率的pandas向量化实现
如果你的时间序列数据量较大,逐行Python循环的效率会很低,可以用pandas内置的分组累计方法实现,不需要写自定义循环:
# 遇到rain=1时累计生成分组编号 group_marker = df['rain'].eq(1).cumsum() # 按分组逐行累计序号,即为距上次降雨的小时数 df['hours_since_rain'] = df.groupby(group_marker).cumcount()
逻辑说明
- 只要
rain列值为1,累计分组编号就会自增,触发新一轮的计数 - 分组内的累计计数从0开始:降雨发生的当行计数为0,后续无雨的行计数依次递增1,完全匹配你需要的统计规则
- 这种向量化实现的计算速度比逐行Python循环快10~100倍,非常适合逐小时的长序列气象数据处理
- 需注意:如果时间序列最开头存在首次降雨发生之前的无雨时段,这类时段的分组编号为0,可根据业务需求将其设为缺失值而非从0开始计数。
用你给出的示例数据验证,最终输出的
hours_since_rain列结果和需求完全匹配:
date rain hours_since_rain 2005-10-15 16:00:00 1 0 2005-10-15 17:00:00 1 0 2005-10-15 18:00:00 0 1 2005-10-15 19:00:00 0 2 2005-10-15 20:00:00 0 3 2005-10-15 21:00:00 0 4 2005-10-15 22:00:00 1 0
内容的提问来源于stack exchange,提问作者Ahegg
相关产品推荐
相关产品推荐

