如何在Python Pandas扩展DataFrame中添加航班日状态信息
问题描述
现有包含航班信息的Pandas DataFrame(df1),其中DIAS_SEMANA列用数字1(周一)至7(周日)表示航班运行的星期几。通过自定义函数expand_date_ranges生成了扩展日期范围的DataFrame(df2),但df2中的DIA列缺失信息,需要填充YES或NO来标识该日期是否有对应航班,需用Python和Pandas高效实现。
给出的原始代码如下:
import pandas as pd df1 = pd.DataFrame({ 'EMPRESA': ['AIR', 'LATAM'], 'NUMERO_DE_VUELO': [901, 504], 'DIAS_SEMANA': ['1237', '12'], 'ORIGEN': ['SCL', 'LIM'], 'DESTINO': ['MIA', 'PUQ'], 'HORA_DESPEGUE': ['21:55', '18:55'], 'INICIO_RANGO': ['03-jun-24', '04-jun-24'], 'FINAL_RANGO': ['08-jun-24', '07-jun-24'] }) def expand_date_ranges(X): df_list = [] for i in range(len(X)): start_date = X.loc[i, 'INICIO_RANGO'] end_date = X.loc[i, 'FINAL_RANGO'] date_range = pd.date_range(start=start_date, end=end_date) for date in date_range: day_of_week = date.weekday() + 1 # 周一=1,周日=7 df_list.append({ 'FECHA': date, 'DIA': '', 'NUMERO_VUELO': X.loc[i, 'NUMERO_DE_VUELO'], 'HORA': X.loc[i, 'HORA_DESPEGUE'], 'ORIGEN': X.loc[i, 'ORIGEN'], 'DESTINO': X.loc[i, 'DESTINO'], 'LINEA_AEREA': X.loc[i, 'EMPRESA'], 'DIA_SEMANA': day_of_week }) df_expanded = pd.DataFrame(df_list) return df_expanded
期望结果:df2的DIA列根据对应航班的DIAS_SEMANA星期代码,填充YES(该日期有航班)或NO(无航班)。
解决方案
方法一:修改生成函数,直接填充DIA列
在遍历日期的过程中,直接判断当前日期的星期数是否属于该航班的运行周期,生成df2时直接完成填充:
import pandas as pd df1 = pd.DataFrame({ 'EMPRESA': ['AIR', 'LATAM'], 'NUMERO_DE_VUELO': [901, 504], 'DIAS_SEMANA': ['1237', '12'], 'ORIGEN': ['SCL', 'LIM'], 'DESTINO': ['MIA', 'PUQ'], 'HORA_DESPEGUE': ['21:55', '18:55'], 'INICIO_RANGO': ['03-jun-24', '04-jun-24'], 'FINAL_RANGO': ['08-jun-24', '07-jun-24'] }) def expand_date_ranges(X): df_list = [] for i in range(len(X)): start_date = X.loc[i, 'INICIO_RANGO'] end_date = X.loc[i, 'FINAL_RANGO'] date_range = pd.date_range(start=start_date, end=end_date) flight_days = X.loc[i, 'DIAS_SEMANA'] # 获取当前航班的运行星期字符串 for date in date_range: day_of_week = str(date.weekday() + 1) # 转字符串方便匹配 # 判断当前星期是否在航班运行列表中 dia_value = 'YES' if day_of_week in flight_days else 'NO' df_list.append({ 'FECHA': date, 'DIA': dia_value, 'NUMERO_VUELO': X.loc[i, 'NUMERO_DE_VUELO'], 'HORA': X.loc[i, 'HORA_DESPEGUE'], 'ORIGEN': X.loc[i, 'ORIGEN'], 'DESTINO': X.loc[i, 'DESTINO'], 'LINEA_AEREA': X.loc[i, 'EMPRESA'], 'DIA_SEMANA': int(day_of_week) }) df_expanded = pd.DataFrame(df_list) return df_expanded # 生成结果 df2 = expand_date_ranges(df1) print(df2)
方法二:生成df2后批量处理(高效版)
如果已经生成了原始df2,可以通过合并df1的星期信息,用Pandas向量操作批量完成判断,避免循环,数据量大时效率更高:
# 先生成原始df2 df2 = expand_date_ranges(df1) # 合并df1的DIAS_SEMANA列到df2 df2 = df2.merge( df1[['NUMERO_DE_VUELO', 'DIAS_SEMANA']], left_on='NUMERO_VUELO', right_on='NUMERO_DE_VUELO', how='left' ) # 批量判断填充DIA列 df2['DIA'] = df2.apply( lambda row: 'YES' if str(row['DIA_SEMANA']) in row['DIAS_SEMANA'] else 'NO', axis=1 ) # 可选:清理临时列 df2 = df2.drop('DIAS_SEMANA_y', axis=1).rename(columns={'DIAS_SEMANA_x': 'DIA_SEMANA'}) print(df2)
核心逻辑说明
两种方法的核心都是:将日期对应的星期数(转为字符串)与航班DIAS_SEMANA字段的字符串进行匹配,存在则填YES,否则填NO。方法一逻辑直观适合小数据量,方法二利用Pandas原生操作,在大数据场景下性能更优。
内容的提问来源于stack exchange,提问作者Gabriel Allende
相关产品推荐
相关产品推荐

