应逐列调用pd.to_datetime或用apply包裹,推荐df[['col_a','col_b','col_c']] = df[['col_a','col_b','col_c']].apply(pd.to_datetime, errors='coerce', format='mixed'),其中format='mixed'自动适配多种格式,errors='coerce'将异常值转为NaT。

直接用 pd.to_datetime 处理多列,但别传 DataFrame 整体
pd.to_datetime 本身不支持直接传入 DataFrame 并自动广播到所有列——那样会报 TypeError: arg must be a string, datetime, list, tuple, 1-d array, or Series。正确做法是逐列调用,或用 apply 包裹。
推荐用 apply + pd.to_datetime 组合,简洁且可控:
df[['col_a', 'col_b', 'col_c']] = df[['col_a', 'col_b', 'col_c']].apply(
pd.to_datetime, errors='coerce', format='mixed'
)
其中 format='mixed' 让 pandas 自动试探多种常见格式(如 '2023-01-01'、'01/01/2023'、'2023-01-01 10:30:00'),比留空 format=None(默认)略快,又比硬写死 format='%Y-%m-%d' 更鲁棒。
errors='coerce' 是必须项,别用 'raise' 或默认
多列混杂脏数据时,errors='raise'(默认行为)会让整条转换失败并中断,哪怕只有一格是 'N/A' 或空字符串;而 errors='coerce' 会把无法解析的值统一转为 NaT(datetime 的 NaN),保留其他有效值。
常见错误场景包括:
- Excel 导出后出现
'NULL'、'#N/A'字符串 - 用户手工填写的
'--'、'/'、空白单元格被读成''或float('nan') - 同一列里混着
'2023-01-01'和'Jan 1, 2023'
所以务必显式写上 errors='coerce',避免静默失败或意外中断。
注意 apply 的 axis 和返回类型,别漏掉赋值
df[col_list].apply(pd.to_datetime, ...) 默认按列(axis=0)执行,返回仍是 DataFrame,每列变成 datetime64[ns] 类型——这是期望行为。
容易出错的点:
- 忘了把结果赋回原 DataFrame:
df[col_list] = ...这一步不能省,否则原 df 不变 - 误用
axis=1:会导致每行拼成一个对象,结果是object类型,完全失效 - 对含时区的列没加
utc=True:如果原始字符串带时区(如'2023-01-01 10:30:00+08:00'),需加utc=True统一转为 UTC 时间戳,否则时区信息丢失
性能敏感时,避免 apply,改用列表推导 + pd.to_datetime
当列数多(比如 >10 列)、每列数据量大(>100 万行)时,apply 有额外函数调用开销。此时可手动循环列名,单列调用更高效:
for col in ['col_a', 'col_b', 'col_c']:
df[col] = pd.to_datetime(df[col], errors='coerce', format='mixed')
它比 apply 快 10%–30%,且更容易插日志或做列级判断(例如跳过已为 datetime64 类型的列)。
真正麻烦的是混合格式列:比如某列前 90% 是 '%Y-%m-%d',后 10% 是 '%d/%m/%Y'。format='mixed' 会 fallback 到慢路径,此时得先清洗或分批处理——这点常被忽略。










