如何处理pandas执行数据操作时出现的OutOfBoundsDatetime报错
问题原因
- 从数据库读取数据时,
end_time这类时间列存在NaT空值,同时可能包含超出 pandas 纳秒时间戳支持范围的异常时间值(比如报错信息里的公元1年时间,pandasdatetime64[ns]仅支持1677-09-21到2262-04-11之间的时间) - 后续对整个 DataFrame 直接执行
fillna('')、applymap(str)、字符串清洗操作时,pandas 会自动尝试将时间列的值重新转换为时间戳,异常值触发边界校验报错
解决方法
方案1:先单独处理时间列,再执行全局清洗
提前把时间列转为字符串,避免后续操作触发自动类型转换:
def data_cleanser(data): clean_df = data.str.strip().str.replace(r'\\', '') return clean_df connection = pyodbc.connect(conn) sql = 'SELECT * FROM {}'.format(tablename) df = pd.read_sql_query(sql, connection) # 新增:把所有时间类型列提前转为字符串,空值直接替换为空字符串 datetime_cols = df.select_dtypes(include=['datetime64', 'datetimetz']).columns for col in datetime_cols: df[col] = df[col].dt.strftime('%Y-%m-%d %H:%M:%S').fillna('') # 后续清洗逻辑调整,只对非时间列做类型转换 df.replace([None], np.nan, inplace=True) df.fillna('', inplace=True) non_datetime_cols = df.select_dtypes(exclude=['datetime64', 'datetimetz']).columns df[non_datetime_cols] = df[non_datetime_cols].applymap(str) df = df.apply(lambda x: data_cleanser(x) if x.dtype == object else x)
方案2:读取数据时直接全量按字符串读取
读数据阶段就禁用时间类型自动推断,从根源避免时间转换问题:
def data_cleanser(data): clean_df = data.str.strip().str.replace(r'\\', '') return clean_df connection = pyodbc.connect(conn) sql = 'SELECT * FROM {}'.format(tablename) # 新增dtype参数,所有列都按字符串格式读取 df = pd.read_sql_query(sql, connection, dtype=str) # 后续清洗逻辑可直接执行,无需调整 df.replace([None, 'NaT'], np.nan, inplace=True) df.fillna('', inplace=True) df = df.apply(lambda x: data_cleanser(x))
补充说明
如果后续需要用到时间列的计算能力,可以在清洗完成后单独对指定列做安全时间转换,过滤异常值:
def safe_to_datetime(val): try: return pd.to_datetime(val) except pd.errors.OutOfBoundsDatetime: return pd.NaT df['start_time'] = df['start_time'].apply(safe_to_datetime) df['end_time'] = df['end_time'].apply(safe_to_datetime)
内容的提问来源于stack exchange,提问作者vvazza
相关产品推荐
相关产品推荐

