如何在Pandas中避免使用循环实现指定的inspection列生成逻辑
问题描述
我希望为DataFrame添加一个inspection列,满足条件:当date_2022列单元格为pd.NaT、date_2021列对应单元格不为pd.NaT,且当前日期与date_2021日期的月日差值超过14天时,将inspection设为'check',否则设为np.nan。请将以下循环代码改写为无循环的Pandas实现方式:
today = pd.Timestamp.today() for x in range(len(df)): #trace back if df.loc[x,'date_2022'] is pd.NaT and df.loc[x,'date_2021'] is not pd.NaT: # extract month and day d1 = today.strftime('%m-%d') d2 = df.loc[x,'date_2021'].strftime('%m-%d') # convert to datetime d1 = datetime.strptime(d1, '%m-%d') d2 = datetime.strptime(d2, '%m-%d') # get difference in days diff = d1 - d2 days = diff.days #range 14 days if days > 14: df.loc[x,'inspection'] = 'check' else: df.loc[x,'inspection'] = np.nan
无循环实现方案
利用Pandas的矢量化操作替代循环,大幅提升运行效率,代码如下:
import pandas as pd import numpy as np today = pd.Timestamp.today() # 将当前日期的月日转为datetime对象(默认年份不影响同年内的天数差计算) today_md = pd.to_datetime(today.strftime('%m-%d'), format='%m-%d') # 批量生成inspection列 df['inspection'] = np.where( # 组合三个判断条件 (df['date_2022'].isna()) & (df['date_2021'].notna()) & ((today_md - pd.to_datetime(df['date_2021'].dt.strftime('%m-%d'), format='%m-%d')).dt.days > 14), 'check', np.nan )
代码说明
- 缺失值判断:用Pandas标准方法
isna()和notna()替代原代码中的is pd.NaT判断,更符合Pandas语法规范。 - 矢量化日期处理:通过
dt.strftime批量提取date_2021的月日信息,再用pd.to_datetime转为日期对象,替代循环中的逐行字符串处理。 - 批量赋值:用
np.where根据布尔条件一次性完成列赋值,无需逐行修改DataFrame。
补充:处理跨年场景(可选)
原代码逻辑中,如果当前日期月日早于date_2021的月日(比如当前是1月5日,date_2021是12月20日),计算出的天数差会为负数,不会标记为check,但实际跨年间隔天数为16天。如果需要修正这个问题,可以调整日期年份:
import pandas as pd import numpy as np today = pd.Timestamp.today() today_full = pd.to_datetime(today.strftime('%Y-%m-%d')) # 将date_2021的月日与当前年份组合,若结果晚于当前日期则年份减1 date_2021_adjusted = pd.to_datetime( today.year.astype(str) + '-' + df['date_2021'].dt.strftime('%m-%d') ) date_2021_adjusted = np.where( date_2021_adjusted > today_full, date_2021_adjusted - pd.DateOffset(years=1), date_2021_adjusted ) # 计算实际间隔天数 days_diff = (today_full - date_2021_adjusted).dt.days # 生成inspection列 df['inspection'] = np.where( (df['date_2022'].isna()) & (df['date_2021'].notna()) & (days_diff > 14), 'check', np.nan )
内容的提问来源于stack exchange,提问作者Rinne Tsujikubo
相关产品推荐
相关产品推荐

