首页 > 解决方案 > 为什么 isinstance 仅在系列地图内返回错误值?

问题描述

对 isinstance 的调用在外部返回 True ,但在一系列地图上的地图内部返回 False (以及数据帧上的应用地图)......

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]

对该系列中的单个值调用 isinstance 会产生 True。

isinstance(s.iloc[0], pd.Timestamp)
True

在该系列的地图内,它给出了 True。

s.map(lambda x: isinstance(x, pd.Timestamp)).iloc[0]
True

但是,如果我们尝试根据该值进行某些操作,例如转换为字符串...

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')

...它似乎返回了 False 并且方法 isoformat 没有被调用(实际的方法调用是无关紧要的,因为它没有被调用)。

标签: pythonpandas

解决方案


查看源代码.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')),
])

.map被调用时,它会检查pd.api.types.is_extension_type(s). 如果s == s1,则返回False,而如果则s == s2返回True

结果,s2.map变成s2._values.map。由于s2._valuesis 的 type ,因此调用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.


推荐阅读