为何pandas.apply遍历Date列时首次返回DatetimeIndex而非Timestamp?
Pandas Date列apply时首次返回DatetimeIndex的原因解析
当前问题
现有如下Pandas DataFrame:
>>> print(my_df) Date Revenue 0 2023-12-27 00:00:00-05:00 3880359 1 2023-12-26 00:00:00-05:00 3139100 2 2023-12-22 00:00:00-05:00 2849700 3 2023-12-21 00:00:00-05:00 4884800 4 2023-12-20 00:00:00-05:00 4032200 5 2023-12-19 00:00:00-05:00 4979100 6 2023-12-18 00:00:00-05:00 6314700 7 2023-12-15 00:00:00-05:00 11503000 8 2023-12-14 00:00:00-05:00 8033300 9 2023-12-13 00:00:00-05:00 7727900
遍历Revenue列时结果符合预期:
>>> my_df['Revenue'].apply(lambda x: print(x, type(x))) 3880359 <class 'int'> 3139100 <class 'int'> 2849700 <class 'int'> 4884800 <class 'int'> 4032200 <class 'int'> 4979100 <class 'int'> 6314700 <class 'int'> 11503000 <class 'int'> 8033300 <class 'int'> 7727900 <class 'int'>
但遍历Date列时出现异常,首次迭代返回了DatetimeIndex对象:
>>> my_df['Date'].apply(lambda x: print(x, type(x))) DatetimeIndex(['2023-12-27 00:00:00-05:00', '2023-12-26 00:00:00-05:00', '2023-12-22 00:00:00-05:00', '2023-12-21 00:00:00-05:00', '2023-12-20 00:00:00-05:00', '2023-12-19 00:00:00-05:00', '2023-12-18 00:00:00-05:00', '2023-12-15 00:00:00-05:00', '2023-12-14 00:00:00-05:00', '2023-12-13 00:00:00-05:00'], dtype='datetime64[ns, America/New_York]', freq=None) <class 'pandas.core.indexes.datetimes.DatetimeIndex'> 2023-12-27 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-26 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-22 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-21 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-20 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-19 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-18 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-15 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-14 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> 2023-12-13 00:00:00-05:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'>
为何会出现这种情况?首次迭代为何返回索引对象?
重现步骤
- 创建
example.json文件,内容如下:
{"Date":{"0":1703653200000,"1":1703566800000,"2":1703221200000,"3":1703134800000,"4":1703048400000,"5":1702962000000,"6":1702875600000,"7":1702616400000,"8":1702530000000,"9":1702443600000},"Revenue":{"0":3880359,"1":3139100,"2":2849700,"3":4884800,"4":4032200,"5":4979100,"6":6314700,"7":11503000,"8":8033300,"9":7727900}}
- 创建
example.py文件,内容如下:
import pandas as pd # 假设example.json和脚本在同一目录 file_path = 'example.json' # 读取JSON生成DataFrame df = pd.read_json(file_path) # 打印DataFrame print(df) # 复现问题 df['Date'].apply(lambda x: print(x, type(x)))
原因分析
核心问题在于pd.read_json的默认行为:当读取包含时间戳的JSON时,它会自动将Date列解析为DatetimeIndex(数据框的索引),而不是常规的Series列。此时调用df['Date']获取的是DatetimeIndex对象,而非Series。
apply方法在DatetimeIndex上的执行逻辑和Series不同:
- 对Series执行
apply,会逐元素传递单个值(比如int或Timestamp) - 对DatetimeIndex执行
apply,会先将整个索引对象作为第一个参数传入lambda,之后再逐元素传递每个Timestamp值
你可以通过以下代码验证这一点:
print(type(df['Date'])) # 输出 <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
解决方法
方法1:读取时禁用自动日期转换
读取JSON时指定convert_dates=False,之后手动将时间戳转换为带时区的Timestamp列:
df = pd.read_json(file_path, convert_dates=False) df['Date'] = pd.to_datetime(df['Date'], unit='ms').dt.tz_localize('America/New_York')
此时df['Date']是Series类型,apply会逐元素传递Timestamp。
方法2:将DatetimeIndex转换为Series后再使用apply
如果不想修改读取逻辑,可以先把DatetimeIndex转为Series:
df['Date'].to_series().apply(lambda x: print(x, type(x)))
内容的提问来源于stack exchange,提问作者AlanSTACK
相关产品推荐
相关产品推荐

