for循环处理datetime.timedelta时pandas时间列赋值异常求解
问题原因
- 循环逻辑存在全量覆盖问题:每一次遍历
j时,df.loc[df['dd'] == 0, 'time']是匹配所有dd等于0的行统一赋值,而非只给第j行赋值。循环执行到最后一轮时,所有行的time字段都会被覆盖为最后一行的时分秒对应值,这是所有行time都显示为2021-07-11 04:56:00的核心原因。 - 额外逻辑错误:你原代码中循环范围写的是
range(len(bc)),如果bc的长度和df行数不一致也会导致取值错误;同时你实际输出里dd=1的行日期仍为7月11日,是因为最后一轮循环执行dd==0的赋值逻辑后,覆盖了之前dd==1行的错误赋值结果。 - 写法冗余:这种逐行赋值的场景不需要写for循环,用pandas向量化操作效率更高、逻辑更清晰,也不容易出现覆盖错误。
修正方案
方案1:修正原有for循环逻辑
如果要保留for循环写法,需要仅针对当前第j行判断dd值再赋值,不要全量匹配:
for j in range(len(df)): hh = df.iloc[j]['hh'] mm = df.iloc[j]['mm'] ss = df.iloc[j]['ss'] if df.iloc[j]['dd'] == 0: df.loc[j, 'time'] = datetime(2021,7,11, hh, mm, ss) else: df.loc[j, 'time'] = datetime(2021,7,12, hh, mm, ss)
方案2:更高效的向量化写法(推荐)
不需要循环,直接用pandas的条件操作实现,性能远高于逐行循环:
df['time'] = df.apply(lambda x: datetime(2021,7,11 if x['dd']==0 else 12, x['hh'], x['mm'], x['ss']), axis=1)
如果数据量较大,可以用更高效的时间拼接写法:
import numpy as np base_date = np.where(df['dd'] == 0, datetime(2021,7,11), datetime(2021,7,12)) df['time'] = pd.to_datetime(base_date) + pd.to_timedelta(df['hh'], unit='h') + pd.to_timedelta(df['mm'], unit='m') + pd.to_timedelta(df['ss'], unit='s')
内容的提问来源于stack exchange,提问作者vp_050
相关产品推荐
相关产品推荐

