pd.to_datetime与np.where结合返回大整数的原因及解决办法
原因
numpy的np.where要求返回的数组必须是统一数据类型。当你尝试混合datetime64[ns](由pd.to_datetime生成)和原object类型的字符串(不匹配正则的元素)时,numpy会自动将datetime64[ns]类型转换为对应的int64整数——因为datetime64[ns]本质是存储从1970-01-01 00:00:00开始的纳秒数,这就是你看到的“大整数”。
而单独调用pd.to_datetime时,pandas的Series可以直接保留datetime64[ns]类型(不匹配的会转为NaT,或根据errors参数处理),不会触发类型强制转换。
解决方法
方法1:使用pandas的Series.where替代np.where
pandas的where方法会更智能地处理类型,能保留datetime64[ns]类型(不符合条件的元素可保留原字符串或设为NaT)。示例代码:
# 假设正则表达式为匹配YYYY-MM-DD格式 mask = df["Day - 2022"].str.match(r'^\d{4}-\d{2}-\d{2}$') # 符合条件的转datetime,不符合的保留原值 df["Day - 2022"] = df["Day - 2022"].where(~mask, pd.to_datetime(df["Day - 2022"]))
注:Series.where的逻辑是保留不符合mask的元素,替换符合mask的元素,因此需要用~mask取反。
方法2:先批量转换,再处理不匹配项
如果允许将不匹配的日期设为NaT(pandas的缺失日期标记),可以直接用pd.to_datetime的errors参数:
df["Day - 2022"] = pd.to_datetime(df["Day - 2022"], errors='coerce')
如果需要将不匹配的元素还原为原字符串,可结合掩码操作:
# 先备份原列 df["Day_original"] = df["Day - 2022"].copy() # 批量转换,不匹配的设为NaT df["Day - 2022"] = pd.to_datetime(df["Day - 2022"], errors='coerce') # 还原不匹配的元素 mask = pd.isna(df["Day - 2022"]) df.loc[mask, "Day - 2022"] = df.loc[mask, "Day_original"] # 可选:删除备份列 df.drop("Day_original", axis=1, inplace=True)
这种方式下,列类型会变为object(混合datetime和字符串),如果不需要保留原字符串,推荐直接用errors='coerce'得到纯datetime64[ns]列。
方法3:强制转换np.where结果类型(不推荐)
如果一定要用np.where,可以先转换结果的类型,但会得到object类型列:
mask = df["Day - 2022"].str.match(r'^\d{4}-\d{2}-\d{2}$') result = np.where( mask, pd.to_datetime(df["Day - 2022"]).values, df["Day - 2022"].values ) df["Day - 2022"] = pd.Series(result, dtype='object')
这种方法会导致列内混合datetime和字符串,后续操作容易出问题,仅在特殊场景下使用。
内容的提问来源于stack exchange,提问作者AK91

