我正在使用不同的索引方法。我有以下工作示例:
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]
任何见识将不胜感激!
答案 0 :(得分:1)
示例的问题在于如何定义a
和b
。如果要打印出x[a, b]
和x[mask]
,您会注意到x[a, b]
的第5和第6元素将与x[mask]
中的第5和第6值一起切换。这样做的原因是,您使用mask
和a
将b
和a
中的每个值设置为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]
解决此问题的一种好方法是先将a
和b
定义为元组列表,先按“ 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]
按照x
和a
给出的顺序从b
中选择元素。结果中,x[a[i], b[i]]
位于x[a[i+1], b[i+1]]
之前。
x[mask]
按行主要顺序遍历mask
来查找True
像元的顺序选择元素。如果x[a, b]
已按字典顺序排序,则此顺序仅与zip(a, b)
相同。
在您失败的示例中,2, 3
在2, 1
和a
中的b
之前,但是以行优先顺序遍历mask
会发现{ True
之前2, 1
的{1}}。因此,2, 3
在x[mask]
之前有x[2, 1]
,而x[2, 3]
的元素则相反。