pandas.eval,带有缺少数据的布尔序列

时间:2017-11-15 10:34:31

标签: python pandas boolean eval missing-data

描述

我在一个缺少数据的布尔序列上使用pandas.eval

为此,我使用索引器标记非空值,.loc仅对具有非缺失数据的行应用.eval

使用表达式~boolnot(bool)应用逻辑非运算符会返回-1或-2。

我明白这是因为我的布尔系列由于缺少值而被转换为对象类型,但我想知道:

  • 为什么-1和-2输出?
  • 在缺少数据的布尔序列中使用.eval的正确方法是什么?

实施例

这是一个使用pandas 0.20.3的可重现的例子。

df = pd.DataFrame({'bool': [True, False, None]})
    bool
0   True
1  False
2   None

indexer = ~pd.isnull(df['bool'])
0     True
1     True
2    False
Name: bool, dtype: bool

df.loc[indexer].eval('~bool')
0    -2
1    -1
Name: bool, dtype: object

1 个答案:

答案 0 :(得分:2)

对于eval~op.invert映射为seen in the source code here

_unary_ops_syms = '+', '-', '~', 'not'
_unary_ops_funcs = op.pos, op.neg, op.invert, op.invert
_unary_ops_dict = dict(zip(_unary_ops_syms, _unary_ops_funcs))

因此,当您的系列版本具有良好的旧object类型时,您在此处看到的是

>>> ~True
-2
>>> ~False
-1

# or with your Series
>>> ~pd.Series(True, dtype='object')
0    -2
dtype: object

你想要的地方

>>> ~pd.Series(True)
0    False
dtype: bool

输出~True -> -2~False -> -1是因为bool是Python中int的子类,而-2,-1是1和0的按位补码。

显而易见的解决方案是预先将系列转换为bool类型,并使用额外的setp中的​​astype(bool),或者如果由于某种原因在eval之前不能这样做,

>>> df.loc[indexer].eval('~bool.astype("bool")')
0    False
1     True
Name: bool, dtype: bool