如何将混合Excel序列号日期与常规日期的列转为pandas datetime?代码排查
解决混合日期格式(常规日期+Excel序列号)的转换问题
我来帮你分析下代码里的问题,以及怎么修复:
问题根源
你的代码主要有两个关键问题导致Excel序列号被转为空白:
错误的Excel序列号判断逻辑
你用df['Birthday'].astype(str).str.isdigit()来筛选Excel序列号,但如果这些序列号在DataFrame里是浮点数类型(比如33233.0),转成字符串后会是"33233.0",str.isdigit()会返回False,导致这些行根本没被处理。就算是字符串形式的"33233.0",同样也过不了isdigit()的检查。后续的全局转换放大了问题
在处理完部分行后,你调用pd.to_datetime(df['Birthday'], errors='coerce'),这会把那些没被处理的Excel序列号(不管是数值还是带小数的字符串)强制转为NaT(空白),因为pd.to_datetime默认无法解析纯数字的日期序列号。
修正后的代码
下面是调整后的代码,我会标注关键修改点:
import pandas as pd import datetime from datetime import datetime, timedelta import glob import os def from_excel_ordinal(ordinal, _epoch0=datetime(1899, 12, 31)): # 处理Excel的1900年闰年bug if ordinal >= 60: ordinal -= 1 return (_epoch0 + timedelta(days=ordinal)).replace(microsecond=0) path = 'C:\\Input' os.chdir(path) filelist = glob.glob('*BLAH*.xlsx') filename = os.fsdecode(filelist[0]) df = pd.read_excel(filename, sheet_name='Blah Blah') # 关键修改1:用pd.to_numeric来判断哪些是Excel序列号(数值类型) # coerce把非数值转成NaN,然后用notna筛选出有效数值行 is_excel_ordinal = pd.to_numeric(df['Birthday'], errors='coerce').notna() # 处理Excel序列号:先转成整数(因为是天数),再转成datetime df.loc[is_excel_ordinal, 'Birthday'] = df.loc[is_excel_ordinal, 'Birthday']\ .astype(int)\ .apply(from_excel_ordinal) # 关键修改2:只处理剩下的非数值行,避免重复处理已经转好的datetime non_ordinal_mask = ~is_excel_ordinal df.loc[non_ordinal_mask, 'Birthday'] = pd.to_datetime( df.loc[non_ordinal_mask, 'Birthday'], errors='coerce' ) # 最后统一列类型为datetime64[ns] df['Birthday'] = pd.to_datetime(df['Birthday'])
关键修改说明
- 更准确的序列号筛选:用
pd.to_numeric(..., errors='coerce')可以识别所有数值类型(int/float)的Excel序列号,不管它们是原始数值还是字符串形式的数字(比如"33233"或"33233.0")。 - 分批次转换:先处理数值型的序列号,再处理剩下的常规日期字符串,避免全局
coerce把已经转好的日期误处理。 - 确保类型统一:最后再把整个列转为datetime类型,保证格式一致。
这样修改后,不管是常规日期字符串还是Excel序列号,都能正确转换为datetime对象,不会出现空白的情况。
内容的提问来源于stack exchange,提问作者Perdue
相关产品推荐
相关产品推荐

