用布尔数组掩盖一系列
这给了我很多麻烦,而且我对numpy数组与熊猫系列的不兼容性感到困惑。 例如,当我使用一系列创建一个布尔数组
x = np.array([1,2,3,4,5,6,7])
y = pd.Series([1,2,3,4,5,6,7])
delta = np.percentile(x, 50)
deltamask = x- y > delta
delta掩码创建一个布尔熊猫系列。
但是,如果你这样做
x[deltamask]
y[deltamask]
你发现数组完全忽略了掩码。 没有错误发生,但最终会得到两个不同长度的对象。 这意味着像一个操作
x[deltamask]*y[deltamask]
导致错误:
print type(x-y)
print type(x[deltamask]), len(x[deltamask])
print type(y[deltamask]), len(y[deltamask])
更令人困惑的是,我注意到操作符<被区别对待。 例如
print type(2*x < x*y)
print type(2 < x*y)
将分别给你一个pd.series和np.array。
也,
5 < x - y
结果是一系列,所以看起来该系列优先,而串行掩码的布尔元素在传递给numpy数组并导致切片数组时被提升为整数。
这是什么原因?
花式索引
作为numpy目前的立场,在numpy的花式索引作品如下:
如果括号之间的东西是一个tuple
(不管是否使用显式元素),则元组的元素是x
不同维度的索引。 例如,在这种情况下, x[(True, True)]
和x[True, True]
会引发IndexError: too many indices for array
,因为x
是1D。 但是,在发生异常之前,会发出警告性警告: VisibleDeprecationWarning: using a boolean instead of an integer will result in an error in the future
。
如果括号之间的东西恰好是一个ndarray
,而不是一个子类或其他类似数组,并且具有布尔类型,则它将作为掩码应用。 这就是为什么x[deltamask.values]
给出预期的结果(空数组,因为deltamask
是False
。
如果括号内的事情是任何阵列状,是否喜欢一个子Series
,或只是一个list
,还是其他什么东西,将它转换成一个np.intp
阵列(如果可能的话),并作为一个整数索引。 因此, x[deltamask]
产生相当于x[[False] * 7]
或x[[0] * 7]
。 在这种情况下, len(deltamask)==7
和x[0]==1
所以结果是[1, 1, 1, 1, 1, 1, 1]
len(deltamask)==7
[1, 1, 1, 1, 1, 1, 1]
。
这种行为是违反直觉的, FutureWarning: in the future, boolean array-likes will be handled as a boolean array index
它生成FutureWarning: in the future, boolean array-likes will be handled as a boolean array index
,表示修复正在进行中。 我会更新这个答案,因为我发现/对numpy进行了任何更改。
这些信息可以在Sebastian Berg对我在这里最初查询Numpy讨论的回应中找到。
关系运算符
现在我们来讨论关于比较如何工作的问题的第二部分。 关系运算符( <
, >
, <=
, >=
)通过调用被比较对象之一的对应方法来工作。 对于<
这是__lt__
。 然而,Python实际上并不是只为表达式x < y
调用x.__lt__(y)
,而是检查被比较对象的类型。 如果y
是实现比较的x
的子类型,那么无论您如何编写原始比较,Python都倾向于调用y.__gt__(x)
。 如果y
是x
的子类,则x.__lt__(y)
将被调用的唯一方法是如果y.__gt__(x)
返回NotImplemented
以指示该方向不支持该比较。
当你做5 < x - y
时会发生类似的事情。 虽然ndarray
不是int
的子类,但比较int.__lt__(ndarray)
返回NotImplemented
,所以Python实际上最终调用(x - y).__gt__(5)
,这当然是定义的,并且工作得很好。
所有这些的更简洁的解释可以在Python文档中找到。
链接地址: http://www.djcxy.com/p/36057.html