numpy中的2D布尔掩码产生不同的结果(掩码排序与原始索引)

时间:2018-11-08 21:39:22

标签: python numpy

我正在使用不同的索引方法。我有以下工作示例:

import numpy as np

x = np.random.rand(321,321)
a = range(0, 300)
b = range(1, 301)
mask = np.zeros(x.shape, dtype=bool)
# a and b are lists 
mask[a, b] = True
assert x[a, b].shape == x[mask].shape  # passes
assert np.isclose(np.sum(x[mask]), np.sum(x[a, b]))  # passes
assert np.allclose(x[mask], x[a, b])  # fails sometimes

当我为项目使用其他x进行尝试时,最后一个断言失败。这是一个失败的案例:

import numpy as np

x = np.random.rand(431,431)
a = [0, 1, 1, 1, 2, 2, 2, 3]
b = [1, 0, 2, 4, 3, 1, 11, 2]

mask = np.zeros(x.shape, dtype=bool)
# a and b are lists 
mask[a, b] = True
assert x[a, b].shape == x[mask].shape  # passes
assert np.isclose(np.sum(x[mask]), np.sum(x[a, b]))  # passes
assert np.allclose(x[mask], x[a, b])  # fails

谁能解释为什么会发生此错误?我认为这是因为mask与(a,b)索引到x的方式不同,但不确定如何。

我想这样做是因为我想轻松获得x[~mask]

任何见识将不胜感激!

3 个答案:

答案 0 :(得分:1)

示例的问题在于如何定义ab。如果要打印出x[a, b]x[mask],您会注意到x[a, b]的第5和第6元素将与x[mask]中的第5和第6值一起切换。这样做的原因是,您使用maskaba中的每个值设置为True,因此顺序并不重要,但是您使用的是b和{ {1}}在您的断言中索引x,因此顺序在那​​里很重要。进行索引时,numpy将从a中获取每个值以从矩阵中获取适当的行,并使用b上相同索引中的值来索引该行。为了说明如何使用3x8数组:

a = [0, 1, 1, 1, 2, 2, 2]
b = [1, 0, 2, 4, 3, 1, 7]

x = [[1, 2, 3, 4, 5, 6, 7, 8],
    [9, 10, 11, 12, 13, 14, 15, 16],
    [17, 18, 19, 20, 21, 22, 23, 24]]

x[a, b] = [2, 9, 11, 13, 20, 18, 24]
mask[a, b] = [2, 9, 11, 13, 18, 20, 24]

解决此问题的一种好方法是先将ab定义为元组列表,先按“ a值”对它们进行排序,然后再按“ b值”对它们进行排序并从那里使用它们。这样您可以保证订单。

答案 1 :(得分:1)

@hpaulj提到了数组的顺序是不同的:

import numpy as np
np.random.seed(42)

x = np.random.rand(431,431)
a = [0, 1, 1, 1, 2, 2, 2, 3]
b = [1, 0, 2, 4, 3, 1, 11, 2]

mask = np.zeros(x.shape, dtype=bool)
# a and b are lists
mask[a, b] = True

print(x[mask])
print(x[a, b])

输出

[0.95071431 0.76151063 0.10112268 0.70096913 0.44076275 0.55964033
 0.40873417 0.20015024]
[0.95071431 0.76151063 0.10112268 0.70096913 0.55964033 0.44076275
 0.40873417 0.20015024]

原因是掩码以行优先(C样式)的顺序返回(请参见docs),并返回multidimensional indexing

  

如果索引数组具有匹配的形状,并且存在索引数组   对于要索引的数组的每个维,结果数组具有   与索引数组具有相同的形状,并且值对应于   为索引数组中每个位置设置的索引。

在您的情况下,多维索引的顺序为:

[(0, 1), (1, 0), (1, 2), (1, 4), (2, 3), (2, 1), (2, 11), (3, 2)]

从蒙版中是:

[(0, 1), (1, 0), (1, 2), (1, 4), (2, 1), (2, 3), (2, 11), (3, 2)]

答案 2 :(得分:1)

x[a, b]按照xa给出的顺序从b中选择元素。结果中,x[a[i], b[i]]位于x[a[i+1], b[i+1]]之前。

x[mask]按行主要顺序遍历mask来查找True像元的顺序选择元素。如果x[a, b]已按字典顺序排序,则此顺序仅与zip(a, b)相同。

在您失败的示例中,2, 32, 1a中的b之前,但是以行优先顺序遍历mask会发现{ True之前2, 1的{​​1}}。因此,2, 3x[mask]之前有x[2, 1],而x[2, 3]的元素则相反。