对isinstance的调用返回True,但在一个系列中的地图内部返回False(以及在数据框上的applymap)...
import pandas as pd
import pytz
s = pd.Series([pd.Timestamp(2018,5,11,6,0,0,0, pytz.timezone('UTC'))])
s
0 2018-05-11 06:00:00+00:00
dtype: datetime64[ns, UTC]
Run Code Online (Sandbox Code Playgroud)
对此系列中单个值的isinstance调用会产生True.
isinstance(s.iloc[0], pd.Timestamp)
True
Run Code Online (Sandbox Code Playgroud)
在系列的地图上,它给出了True.
s.map(lambda x: isinstance(x, pd.Timestamp)).iloc[0]
True
Run Code Online (Sandbox Code Playgroud)
但是如果我们尝试一些取决于该值的东西,比如转换为字符串......
s.map(lambda x: x.isoformat() if isinstance(x, pd.Timestamp) else x).iloc[0]
Timestamp('2018-05-11 06:00:00+0000', tz='UTC')
Run Code Online (Sandbox Code Playgroud)
...它似乎返回了False并且没有调用方法isoformat(实际的方法调用是无关紧要的,因为它没有被调用).
查看来源,似乎.mapPandas 正在检查 Series 的类型是否是扩展类型。正如OP指出的,这对于不同的时区会有不同的表现。让
s1 = pd.Series([
pd.Timestamp(2018,5,11,6,0,0,0),
])
s2 = pd.Series([
pd.Timestamp(2018,5,11,6,0,0,0, pytz.timezone('UTC')),
])
Run Code Online (Sandbox Code Playgroud)
当.map被调用时,它会检查pd.api.types.is_extension_type(s). 如果s == s1,则返回False,而如果则s == s2返回True。
结果,s2.map变成了s2._values.map。由于s2._values是 类型,因此调用DatetimeIndex的相关实现。.map它首先尝试调用并在发生错误时f(s2._values)恢复。s2._values.map(f)
在这种情况下,f = lambda x: x.isoformat(x) if isinstance(x, pd.Timestamp) else x。不会发生错误,因为f检查 ifisinstance(s2._values, pd.Timestamp)失败。因此,f(s2._values)返回s2._values。确实,这一点可以用 来验证s2._values is f(s2._values) == True。
一种解决方法是确保pd.api.types.is_extension_type不调用 ,例如s.astype(object).map。