【问题标题】:How exactly does numpy.where() select the elements in this example?numpy.where() 究竟是如何选择这个例子中的元素的?
【发布时间】:2019-02-02 04:39:46
【问题描述】:

来自 numpy docs

>>> np.where([[True, False], [True, True]],
    ...          [[1, 2], [3, 4]],
    ...          [[9, 8], [7, 6]])
array([[1, 8],
       [3, 4]])

我是否正确假设 [[True, False], [True, True]] 部分是条件,[[1, 2], [3, 4]][[9, 8], [7, 6]] 根据文档参数分别是 x 和 y。

那么在以下示例中,函数选择元素的准确程度如何?

另外,为什么这些示例中的元素类型是列表?

>>> np.where([[True, False,True], [False, True]], [[1, 2,56], [3, 4]], [[9, 8,79], [7, 6]])
array([list([1, 2, 56]), list([3, 4])], dtype=object)
>>> np.where([[False, False,True,True], [False, True]], [[1, 2,56,69], [3, 4]], [[9, 8,90,100], [7, 6]])
array([list([1, 2, 56, 69]), list([3, 4])], dtype=object)

【问题讨论】:

  • 你的下一个问题表明这些答案并不能让你满意。您可能需要解释什么是令人困惑的。现在远离第二个例子;它只会让你感到困惑。

标签: python python-3.x numpy


【解决方案1】:

在第一种情况下,每个术语都是一个(2,2) 数组(或者更确切地说是可以组成这样一个数组的列表)。对于条件中的每个True,它返回x 中的对应术语[[1 -][3,4]],对于每个False,它返回来自y 的术语[[- 8][- -]]

在第二种情况下,列表参差不齐

In [1]: [[True, False,True], [False, True]]
Out[1]: [[True, False, True], [False, True]]
In [2]: np.array([[True, False,True], [False, True]])
Out[2]: array([list([True, False, True]), list([False, True])], dtype=object)

数组是 (2,),有 2 个列表。当转换为布尔值时,一个 2 元素数组,两者都为 True。只有空列表会产生 False。

In [3]: _.astype(bool)
Out[3]: array([ True,  True])

where 然后只返回 x 值。

这第二种情况是可以理解的,但却是病态的。

更多详情

让我们用一个更简单的例子更详细地演示where。相同的条件数组:

In [57]: condition = np.array([[True, False], [True, True]])
In [58]: condition
Out[58]: 
array([[ True, False],
       [ True,  True]])

单参数版本,相当于condition.nonzero():

In [59]: np.where(condition)
Out[59]: (array([0, 1, 1]), array([0, 0, 1]))

有些人发现更容易可视化该元组的 transpose - condition 为 True 的 3 对坐标:

In [60]: np.argwhere(condition)
Out[60]: 
array([[0, 0],
       [1, 0],
       [1, 1]])

现在是最简单的版本,带有 3 个参数,带有标量值。

In [61]: np.where(condition, True, False)   # same as condition
Out[61]: 
array([[ True, False],
       [ True,  True]])
In [62]: np.where(condition, 100, 200)
Out[62]: 
array([[100, 200],
       [100, 100]])

可视化此操作的一个好方法是使用两个掩码分配。

In [63]: res = np.zeros(condition.shape, int)
In [64]: res[condition] = 100
In [65]: res[~condition] = 200
In [66]: res
Out[66]: 
array([[100, 200],
       [100, 100]])

另一种方法是使用y 值初始化一个数组,并在其中填充x 值的非零值。

In [69]: res = np.full(condition.shape, 200)
In [70]: res
Out[70]: 
array([[200, 200],
       [200, 200]])
In [71]: res[np.where(condition)] = 100
In [72]: res
Out[72]: 
array([[100, 200],
       [100, 100]])

如果 xy 是数组,而不是标量,则此掩码赋值将需要改进,但希望首先这会有所帮助。

【讨论】:

  • 非常感谢,我想即使是复杂的例子我也完全理解了。
【解决方案2】:

np.where(condition,x,y) 它检查条件,如果它的 True 返回 x,否则它返回 y

np.where([[True, False], [True, True]], [[1, 2], [3, 4]], [[9, 8], [7, 6]])

这里你的条件是[[True, False], [True, True]] x = [[1 , 2] , [3 , 4]] y = [[9 , 8] , [7 , 6]]

第一个条件为真,所以它返回 1 而不是 9

第二个条件为假,所以它返回 8 而不是 2

【讨论】:

    【解决方案3】:

    在阅读了@hpaulj 建议的broadcasting 之后,我想我知道该功能是如何工作的。 它将尝试广播 3 个数组,然后如果广播成功,它将使用 TrueFalse 值从 x 或 y 中选择元素。 在示例中

    >>>np.where([[True, False,True], [False, True]], [[1, 2,56], [3, 4]], [[9, 8,79], [7, 6]])
    

    我们有

    cnd=np.array([[True, False,True], [False, True]])
    x=np.array([[1, 2,56], [3, 4]])
    y=np.array([[9, 8,79], [7, 6]])
    

    现在

    >>>x.shape
    Out[7]: (2,)
    >>>y.shape
    Out[8]: (2,)
    >>>cnd.shape
    Out[9]: (2,)
    

    所以这三个都只是具有 2 个元素(列表类型)的数组,甚至是条件(cnd)。所以[True, False,True][False, True] 都将被评估为True。这两个元素都将从 x 中选择.

    >>>np.where([[True, False,True], [False, True]], [[1, 2,56], [3, 4]], [[9, 8,79], [7, 6]])
    Out[10]: array([list([1, 2, 56]), list([3, 4])], dtype=object)
    

    我还尝试了一个更复杂的示例(2x2x2 广播),它仍然可以解释它。

    np.where([[[True,False],[True,True]], [[False,False],[True,False]]],
              [[[12,45],[10,50]], [[100,10],[17,81]]],
              [[[90,93],[85,13]], [[12,345], [190,56,34]]])
    

    在哪里

    cnd=np.array([[[True,False],[True,True]], [[False,False],[True,False]]])
    x=np.array([[[12,45],[10,50]], [[100,10],[17,81]]])
    y=np.array( [[[90,93],[85,13]], [[12,345], [190,56,34]]])
    

    这里cndx 的形状为(2,2,2)y 的形状为(2,2)

    >>>cnd.shape
    Out[14]: (2, 2, 2)
    >>>x.shape
    Out[15]: (2, 2, 2)
    >>>y.shape
    Out[16]: (2, 2)
    

    现在@hpaulj 评论y 将被广播到 (2,2,2)。 它可能看起来像这样

    >>>cnd
    Out[6]: 
    array([[[ True, False],
            [ True,  True]],
           [[False, False],
            [ True, False]]]) 
    >>>x
    Out[7]: 
    array([[[ 12,  45],
            [ 10,  50]],
           [[100,  10],
            [ 17,  81]]])
    >>>np.broadcast_to(y,(2,2,2))
    Out[8]: 
    array([[[list([90, 93]), list([85, 13])],
            [list([12, 345]), list([190, 56, 34])]],
           [[list([90, 93]), list([85, 13])],
            [list([12, 345]), list([190, 56, 34])]]], dtype=object)
    

    而且结果很容易预测为

    >>>np.where([[[True,False],[True,True]], [[False,False],[True,False]]], [[[12,45],[10,50]], [[100,10],[17,81]]],[[[90,93],[85,13]], [[12,345], [190,56,34]]])
    Out[9]: 
    array([[[12, list([85, 13])],
            [10, 50]],
           [[list([90, 93]), list([85, 13])],
            [17, list([190, 56, 34])]]], dtype=object)
    

    【讨论】:

      猜你喜欢
      • 2017-11-15
      • 2018-03-03
      • 2014-01-03
      • 2020-08-21
      • 1970-01-01
      • 2018-01-19
      • 2018-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多