为什么isinstance仅在系列映射中返回错误的值?

Yma*_*eth 7 python pandas

对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(实际的方法调用是无关紧要的,因为它没有被调用).

hil*_*lem 3

查看来源似乎.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