Numpy非反对角线花式索引

jm81lzqq  于 2023-08-05  发布在  其他
关注(0)|答案(3)|浏览(88)

有没有可能使用NumPy切片将下面的花哨索引转换为基本索引?

import numpy as np
fancy_indices = np.arange(10), 18 - np.arange(10)
source = np.arange(400).reshape(20, 20)
 
target = source[fancy_indices]

字符串
这些花哨的索引指向矩阵的非反对角线元素。元素之间的步幅也是固定的。有没有一种方法可以使用基本的索引,而不是花哨的索引,来实现相同的target(这样返回的数组就不拥有数据,也不是内存连续的),同时仍然具有可读的代码?

xiozqbni

xiozqbni1#

In [40]: target
Out[40]: array([ 18,  37,  56,  75,  94, 113, 132, 151, 170, 189])
In [48]: res = np.diagonal(source[:,::-1],1)[:10]
In [49]: res
Out[49]: array([ 18,  37,  56,  75,  94, 113, 132, 151, 170, 189])

字符串
res是源代码的view,但它是只读的:

In [54]: source[0,18]=1000
In [55]: res
Out[55]: array([1000,   37,   56,   75,   94,  113,  132,  151,  170,  189])

In [56]: res[0]=18
---------------------------------------------------------------------------
ValueError: assignment destination is read-only


查看np.diag的代码,我们可以看到它使用arr.flat索引。因此我们可以直接用以下公式获得目标:

In [59]: source.flat[18:190:19]
Out[59]: array([1000,   37,   56,   75,   94,  113,  132,  151,  170,  189])


不过,这并不是一个view
np.diagonal记录了只读视图位。还演示了反对角线。np.diag使用np.diagonal(如果给定2D数组)。arr.diagonal被编译,但是np.diag使用flat技巧来创建对角矩阵。
在评论中,我提到了使用as_strided。这样得到10个反对角线元素,但从19个开始,而不是18个。但是对于这个目的,flat更容易使用。

In [80]: np.lib.stride_tricks.as_strided(source[:,::-1], (10,), (152,))
Out[80]: array([ 19,  38,  57,  76,  95, 114, 133, 152, 171, 190])

ymdaylpp

ymdaylpp2#

我认为这是困难的,因为切片只在每个轴上执行。你可以做的是使用生成器,它的优点是不会分配内存。例如:

gen1 = (i for i in np.arange(10))
gen2 = (i for i in 18 - np.arange(10))

target = []
for i,j in zip(gen1, gen2):
    target.append(source[i,j])

字符串

kse8i1jr

kse8i1jr3#

受@hpaulj的回答启发,我认为最有效的内存方法是

np.diagonal(source[:,::-1],1)[:10]

字符串
或者是

target = np.diagonal(source[:, :18-10:-1], source.shape[1] - 1 - 18)
source.flat[[18, 37]] += 100  # this will be reflected in target

相关问题