【问题标题】:Logical indices in numpy throwing exception [duplicate]numpy抛出异常中的逻辑索引[重复]
【发布时间】:2015-12-15 17:53:30
【问题描述】:

我正在尝试编写一些代码,使用逻辑 numpy 数组来索引更大的数组,类似于 MATLAB 允许使用逻辑数组进行数组索引的方式。

import numpy as np
m = 4
n = 4
unCov = np.random.randint(10, size = (m,n) )
rowCov = np.zeros( m, dtype = bool )
colCov = np.ones( n, dtype = bool )
>>> unCov[rowCov, rowCov] 
[]  # as expected
>>> unCov[colCov, colCov]
[0 8 3 3]  # diagonal values of unCov, as expected
>>> unCov[rowCov, colCov]
ValueError: shape mismatch: objects cannot be broadcast to a single shape

对于最后一次评估,我期望一个空数组,类似于 MATLAB 返回的内容。我宁愿不必在索引之前检查 rowCov/colCov 的 True 元素。为什么会发生这种情况,有没有更好的方法来做到这一点?

【问题讨论】:

  • Umm...matlab 在后一种情况下返回完整矩阵,而不是对角线值。对不对?
  • @Andras 哦,好点,你是对的!抱歉,我没有关注 MATLAB 比较的这方面。我猜 numpy 和 MATLAB 在这方面比我意识到的要大得多。
  • 看看这个similar question我想它回答了你的问题。
  • @Bi Rico:是的,谢谢!这正是我想要的效果!

标签: python arrays matlab python-3.x numpy


【解决方案1】:

据我了解,numpy 会将您的 2d 逻辑索引转换为实际索引向量:arr[[True,False],[False,True]] 将变为 arr[0,1] 用于形状为 ndarrayndarray。但是,在您的最后一种情况下,第二个索引数组是完整的False,因此它对应于长度为 0 的索引数组。这与另一个完整的True 索引向量配对,对应于长度为 4 的索引数组。

来自the numpy manual

如果索引数组的形状不同,则尝试 将它们广播到相同的形状。如果它们不能被广播到 相同的形状,引发异常:

在您的情况下,错误正是由于以下原因:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-1411-28e41e233472> in <module>()
----> 1 unCov[colCov,rowCov]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (0,)

另一方面,如果索引数组在任何给定维度上为空,MATLAB 会自动返回一个空数组。


这实际上突出了 MATLAB 和 numpy 中的逻辑索引之间的根本区别。在 MATLAB 中,下标索引中的向量总是切出一个子数组。也就是说,两者都

arr([1,2],[1,2])

arr([true,true],[true,true])

将返回矩阵arr2 x 2 子矩阵。如果逻辑索引向量短于数组的给定维度,则假定缺少的索引元素为false。有趣的事实:索引向量也可以比给定的维度长,只要超出的元素都是false。所以上面也等价于

arr([true,true,false,false],[true,true])

arr([true,true,false,false,false,false,false],[true,true])

对于4 x 4 数组(为了论证)。

然而,在 numpy 中,以这种方式使用布尔值 numpy arrays 进行索引将尝试提取向量。此外,布尔索引向量的长度应与它们索引的维度相同。在您的4 x 4 示例中,

unCov[np.array([True,True]),np.array([True,True])]

unCov[np.array([True,True,False,False,False]),np.array([True,True,False,False,False])]

都返回两个第一个对角线元素,所以不是子矩阵而是向量。此外,他们还给出了不那么令人鼓舞的警告

/usr/bin/ipython:1: VisibleDeprecationWarning: boolean index did not match indexed array along dimension 0; dimension is 4 but corresponding boolean dimension is 5

因此,在 numpy 中,您的逻辑索引向量的长度应与 ndarray 的相应维度相同。然后我上面写的也是正确的:逻辑值被转换为索引,结果应该是一个向量。这个向量的长度是每个索引向量中 True 元素的数量,所以如果你的布尔索引向量有不同数量的 True 元素,那么引用没有意义,你会得到错误得到。

【讨论】:

  • 我基本上是要写这个的。 +1。
  • 感谢您的解释...非常好的信息!如果不首先检查其中一个数组是否全部为 False,就无法执行像 unCov[rowCov, colCov] 这样的一般索引,这似乎有点非 Pythonic。无赖。
猜你喜欢
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 2013-03-23
  • 2013-03-07
相关资源
最近更新 更多