如何使用numpy数组的引用坐标处理奇怪的索引行为?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用numpy数组的引用坐标处理奇怪的索引行为?相关的知识,希望对你有一定的参考价值。
作为一个更大的项目的一部分,我正在生成一堆不同大小的不同坐标列表,当我尝试使用这些坐标列表作为数组的索引时,我发现了一些奇怪的行为。这些坐标列表是在程序中生成的,所以我不知道它们会有多长。请参阅下面的示例:
t = np.zeros((5,5))
coord = [[2,3], [1,2]]
t[coord] = 30
print(t)
输出:
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[ 0. 30. 0. 0. 0.]
[ 0. 0. 30. 0. 0.]
[ 0. 0. 0. 0. 0.]]
但是如果列表只有一点:
t = np.zeros((5,5))
coord = [[2,3]]
t[coord] = 30
print(t)
输出:
[[ 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0.]
[30. 30. 30. 30. 30.]
[30. 30. 30. 30. 30.]
[ 0. 0. 0. 0. 0.]]
然后,如果我将列表转换为numpy数组,它会进一步分解:
t = np.zeros((5,5))
coord = np.array([[2,3], [1,2]])
t[coord] = 30
print(t)
输出:
[[ 0. 0. 0. 0. 0.]
[30. 30. 30. 30. 30.]
[30. 30. 30. 30. 30.]
[30. 30. 30. 30. 30.]
[ 0. 0. 0. 0. 0.]]
我如何处理这个,所以我总是得到第一个输出,即使只有一个元素,它是一个numpy数组?
谢谢!
编辑:
我的代码中正在发生的事情是程序返回一个点数组:
array([[ 9, 5, 0],
[ 4, 2, 2],
[11, 4, 2],
[ 5, 7, 2],
[11, 12, 2],
[12, 9, 0],
[ 5, 4, 7],
[ 3, 2, 1],
...
然后我想用它来改变更大的14 * 14 * 9矩阵中的这些坐标点。 big_matrix [coord] = 0
EDIT2:基于@hpaulj的评论
以下是完整规模问题的示例:
coord = np.array([[ 4, 7, 0],
[ 9, 6, 1],
[ 8, 2, 0],
[ 8, 7, 6],
[ 3, 10, 4],
[ 6, 4, 3],
[10, 10, 3],
[ 3, 2, 1]], dtype='int32')
matrix[coord]
收益:
array([[[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]],
索引赋值可以模糊一些细节,我认为getitem
等价物更清晰。
In [88]: arr = np.arange(25).reshape(5,5)
In [89]: arr
Out[89]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
In [90]: coord = [[2,3],[1,2]]
In [91]: arr[coord]
FutureWarning: Using a non-tuple sequence for multidimensional indexing
is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the
future this will be interpreted as an array index, `arr[np.array(seq)]`,
which will result either in an error or a different result.
Out[91]: array([11, 17])
正确索引一对点,对第一轴应用[2,3],对第二轴应用[1,2]:
In [92]: coord = ([2,3],[1,2])
In [93]: arr[coord]
Out[93]: array([11, 17])
In [94]: arr[[2,3], [1,2]]
Out[94]: array([11, 17])
历史上numpy
有点草率,并解释了列表列表,如列表元组(在某些情况下)。较新的版本试图消除这种不一致。
In [95]: coord = [[2,3]]
In [96]: arr[coord]
FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
Out[96]:
array([[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
In [97]: coord = ([2,3],) # clearer - pick 2 rows, e.g. arr[[2,3],:]
In [98]: arr[coord]
Out[98]:
array([[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
In [99]: arr[2,3] # pick one point
Out[99]: 13
In [100]: coord = (2,3)
In [101]: arr[coord]
Out[101]: 13
有了这个数组,没有一个令人困惑的元组列表:
In [102]: coord = np.array([[2,3], [1,2]])
In [103]: arr[coord]
Out[103]:
array([[[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]])
这会选择一个(2,2)块行。你的arr[coord]=30
模糊了这种模式,因为行选择中有重复(并且赋值被缓冲)。 (对于无缓冲的分配,测试np.add.at(t,coord,30)
)。
如果我们明确告诉它coord
适用于第一维,我们采用相同的索引数组样式:
In [111]: coord = [[2,3],[1,2]]
In [112]: arr[coord,:]
Out[112]:
array([[[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]])
如果我将最后一个[coord,]
与1个元素列表一起使用,请注意形状上的差异:
In [117]: coord = [[2,3]]
In [118]: arr[coord,]
Out[118]:
array([[[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]]])
In [119]: _.shape
Out[119]: (1, 2, 5)
因此,如果您希望每个元素应用于不同的维度,请将coord
设为元组而不是列表。或者如果您希望将数组应用于一个维度,则使用数组,或者使用[coord,:]
作为符号显式使用数组。
如果您使用此数组,将其转置,并将其拆分为元组,您将获得2维的索引数组:
In [120]: coord = np.array([[2,3],[1,2]])
In [121]: coord
Out[121]:
array([[2, 3],
[1, 2]])
In [123]: tuple(coord.T)
Out[123]: (array([2, 1]), array([3, 2]))
In [124]: arr[tuple(coord.T)]
Out[124]: array([13, 7])
并有4分:
In [125]: coord = np.array([[2,3],[1,2],[0,0],[3,4]])
In [126]: arr[tuple(coord.T)]
Out[126]: array([13, 7, 0, 19])
我不知道这是否有帮助,但np.where
经常用于选择数组中的点:
条件 - 4的倍数:
In [135]: arr%4==0
Out[135]:
array([[ True, False, False, False, True],
[False, False, False, True, False],
[False, False, True, False, False],
[False, True, False, False, False],
[ True, False, False, False, True]])
这些点的索引 - 每个维度都有一个数组的元组。这可以直接用作索引:
In [136]: np.where(arr%4==0)
Out[136]: (array([0, 0, 1, 2, 3, 4, 4]), array([0, 4, 3, 2, 1, 0, 4]))
In [137]: arr[_]
Out[137]: array([ 0, 4, 8, 12, 16, 20, 24])
argwhere
将np.transpose
应用于该元组,制作一个(n,2)数组:
In [138]: np.argwhere(arr%4==0)
Out[138]:
array([[0, 0],
[0, 4],
[1, 3],
[2, 2],
[3, 1],
[4, 0],
[4, 4]])
这些是各个元素的坐标,但它们不能直接用作索引,迭代除外:
In [144]: [arr[i,j] for i,j in np.argwhere(arr%4==0)]
Out[144]: [0, 4, 8, 12, 16, 20, 24]
我认为你在这个argwhere
风格中生成坐标,但你真的需要它们在where
风格 - 作为数组的元组。
以上是关于如何使用numpy数组的引用坐标处理奇怪的索引行为?的主要内容,如果未能解决你的问题,请参考以下文章