【问题标题】:What is the purpose of numpy.where returning a tuple?numpy.where 返回元组的目的是什么?
【发布时间】:2018-11-11 18:05:28
【问题描述】:

当我运行这段代码时:

import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
print(np.where(a > 2))

得到a > 2 的索引数组是很自然的,即[2, 3, 4, 5],但我们得到的是:

(array([2, 3, 4, 5], dtype=int64),)

即第二个成员为空的元组。

那么,要得到numpy.where的“自然”答案,我们必须这样做:

np.where(a > 2)[0]

这个元组有什么意义?在什么情况下有用?

注意:我在这里只谈论用例 numpy.where(cond) 而不是同样存在的 numpy.where(cond, x, y)(参见文档)。

【问题讨论】:

  • 注意:我已经阅读了stackoverflow.com/questions/5642457/…,但它没有解释这部分。
  • (3,) 是一个单元素元组。没有“第二个元素”,无论是否为空。
  • 是的@hpaulj,但是如果w = ([13, 14, 15], ),那么我们仍然需要w[0][1] 来获得14 而不是w[1],这就是我的意思:[0] 是检索 元组的第一个元素.
  • np.where 使用np.nonzero,它更明确地返回一个元组,每个维度一个数组。它不是特例 1d。
  • 最初我认为这允许使用例如元组索引a[np.where(a > 2)],但实际上这适用于有或没有一元元组的一维情况。

标签: python arrays numpy


【解决方案1】:

numpy.where 返回一个元组,因为元组的每个元素都指向一个维度。

在二维中考虑这个例子:

a = np.array([[1, 2, 3, 4, 5, 6],
              [-2, 1, 2, 3, 4, 5]])

print(np.where(a > 2))

(array([0, 0, 0, 0, 1, 1, 1], dtype=int64),
 array([2, 3, 4, 5, 3, 4, 5], dtype=int64))

可以看到,元组的第一个元素是指相关元素的第一个维度;第二个元素是指第二个维度。

这是numpy 经常使用的约定。当您询问数组的形状时,您也会看到它,即一维数组的形状将返回一个具有 1 个元素的元组:

a = np.array([[1, 2, 3, 4, 5, 6],
              [-2, 1, 2, 3, 4, 5]])

print(a.shape, a.ndim)  # (2, 6) 2

b = np.array([1, 2, 3, 4, 5, 6])

print(b.shape, b.ndim)  # (6,) 1

【讨论】:

    【解决方案2】:

    来自np.where的文档

    如果只给出条件,则返回元组condition.nonzero(),条件为真的索引

    所以我们查看'np.nonzero'的文档

    返回一个数组元组,每个维度对应一个数组,其中包含该维度中非零元素的索引。 a 中的值始终以行优先的 C 样式顺序进行测试和返回。对应的非零值可以通过以下方式获得:

    那么对于np.where/np.nonzero 返回一个数组元组有用 怎么办?我认为它与indexing multi-dimensional arrays 有关。

    如果我们有documentation的例子

    y = np.arange(35).reshape(5,7)
    

    我们可以的

    y[np.array([0,2,4]), np.array([0,1,2])]
    

    选择y[0, 0]y[2, 1]y[4, 2]

    在这种情况下,如果索引数组具有匹配的形状,并且被索引的数组的每个维度都有一个索引数组,则结果数组与索引数组具有相同的形状,并且值对应于索引为索引数组中的每个位置设置。在此示例中,两个索引数组的第一个索引值为 0,因此结果数组的第一个值为 y[0,0]。下一个值是 y[2,1],最后一个是 y[4,2]。

    希望索引多维数组能够证明np.nonzero/np.where 返回一个数组元组,以便以后可以使用它来选择元素。

    【讨论】:

    • 对于一维情况,无论返回值是否包含在 1 元素元组中,花哨的索引都有效。
    • @wim 是真的!
    • 您引用的文档中的文本似乎已被删除,根本没有引用元组。
    • @vcovo 实际上,这看起来像是“文档回归”。看起来该信息已被删除以支持该注释以直接使用nonzero。这种行为似乎仍然存在,但现在记录得不太清楚:(
    【解决方案3】:

    为了一致性:元组的长度与输入数组的维数相匹配。

    >>> np.where(np.ones((1)) > 0)
    (array([0]),)
    >>> np.where(np.ones((1,1)) > 0)
    (array([0]), array([0]))
    >>> np.where(np.ones((1,1,1)) > 0)
    (array([0]), array([0]), array([0]))
    

    使一维情况返回数组而不是元组会导致返回类型不均匀。如果调用者代码正在处理任意形状的输入数据,那么程序员将不得不对返回值中的一维输入进行特殊情况处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      • 2011-01-05
      • 2020-10-17
      相关资源
      最近更新 更多