
本文介绍如何在python中从包含混合文本的csv列中安全提取标准日期(如yyyy-mm-dd),并准确筛选出非最大日期的记录,避免因直接解析失败导致的nan干扰。
在处理真实业务数据时,csv中的日期常以“2024-01-02 rev. 003”这类带后缀的字符串形式存在。若直接对原始字符串调用 pd.to_datetime()(如 pd.to_datetime(df[‘Version’], format=’%Y-%m-%d’)),pandas 会因格式不匹配而返回 NaT(Not a Time),进而导致 max() 计算失效或 ne() 比较产生意外空结果——这正是提问者遇到 NULL value is coming 的根本原因。
正确做法是先提取、再转换、后过滤,分三步确保鲁棒性:
- 正则提取纯日期子串:使用 str.extract(r'(d{4}-d{2}-d{2})’) 从每行文本中捕获形如 YYYY-MM-DD 的日期片段;
- 安全转为 datetime 类型:对提取结果调用 pd.to_datetime(…, errors=”coerce”),将非法值转为 NaT,不影响后续逻辑;
- 基于提取后的日期序列进行布尔索引过滤:仅对有效日期比较 ne(dates.max()),自动忽略 NaT 行(因 NaT != any_value 恒为 False,不会被误选)。
✅ 完整可运行示例:
import pandas as pd # 构造示例数据 df3 = pd.DataFrame({ 'Version': [ '2024-01-02 rev. 003', '2024-01-02 rev. 003', '2023-11-17 rev. 003' ] }) # 步骤1:提取日期字符串 s = df3['Version'].str.extract(r'(d{4}-d{2}-d{2})', expand=False) # 步骤2:转为datetime,错误值设为NaT dates = pd.to_datetime(s, format='%Y-%m-%d', errors='coerce') # 步骤3:过滤掉日期等于最大有效日期的所有行 df3_filtered = df3[dates.ne(dates.max())].copy() print(df3_filtered) # 输出: # Version # 2 2023-11-17 rev. 003
⚠️ 注意事项:
- 正则 r'(d{4}-d{2}-d{2})’ 假设日期严格符合 YYYY-MM-DD 格式;若存在 YY-M-D 或其他变体,需调整正则(如 r'(d{4}-d{1,2}-d{1,2})’ 并配合 infer_datetime_format=True);
- 若原始列含完全无日期的行(如 “N/A” 或空字符串),str.extract 返回 NaN,pd.to_datetime 将其转为 NaT,这些行在 dates.ne(dates.max()) 中自然被排除,符合多数业务预期;
- 如需保留原始 Version 列不变,建议使用 .copy() 避免 SettingWithCopyWarning。
该方法兼顾准确性与健壮性,是处理非结构化日期文本的标准实践。