生成NumPy矩阵的矢量化解法

2024-03-28 23:32:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一些内置的NumPy模块或一些向量化的方法来获得这样的n矩阵。这里唯一的关键是给定行的最后一个元素作为下一行的第一个元素。你知道吗

n = 2
# array([[1, 2], 
#        [2, 3]])

n = 3
# array([[1, 2, 3], 
#        [3, 4, 5], 
#        [5, 6, 7]])

n = 4
# array([[1, 2, 3, 4], 
#        [4, 5, 6, 7], 
#        [7, 8, 9, 10], 
#        [10, 11, 12, 13]])

我尝试使用列表理解。同样可以用扩展for循环语法编写。你知道吗

import numpy as np
n = 4
arr = np.array([[(n-1)*j+i for i in range(1, n+1)] for j in range(n)])
# array([[ 1,  2,  3,  4],
#        [ 4,  5,  6,  7],
#        [ 7,  8,  9, 10],
#        [10, 11, 12, 13]])

Tags: 模块方法inimportnumpy元素列表for
3条回答

如果您想保持简单(并且有一定的可读性),应该这样做:

def ranged_mat(n):
    out = np.arange(1, n ** 2 + 1).reshape(n, n)
    out -= np.arange(n).reshape(n, 1)
    return out

只需构建从1到n²的所有数字,将其重塑为所需的块形状,然后从每行中减去行号。你知道吗

这与Divakar的ranged_mat_v2相同,但我喜欢用中间数组形状显式表示。不是每个人都是NumPy广播规则的专家。你知道吗

进近#1

我们可以利用基于^{}^{}来获得滑动窗口。More info on use of ^{} based ^{}。你知道吗

另外,它接受一个step参数,这非常适合这个问题。因此,实施将是——

from skimage.util.shape import view_as_windows

def ranged_mat(n):
    r  = np.arange(1,n*(n-1)+2)
    return view_as_windows(r,n,step=n-1)

示例运行-

In [270]: ranged_mat(2)
Out[270]: 
array([[1, 2],
       [2, 3]])

In [271]: ranged_mat(3)
Out[271]: 
array([[1, 2, 3],
       [3, 4, 5],
       [5, 6, 7]])

In [272]: ranged_mat(4)
Out[272]: 
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10],
       [10, 11, 12, 13]])

进近#2

另一个是^{}-

def ranged_mat_v2(n):
    r = np.arange(n)
    return (n-1)*r[:,None]+r+1

进近#3

我们还可以使用支持多核处理的^{} module,从而在大型n's上获得更好的效率-

import numexpr as ne

def ranged_mat_v3(n):
    r = np.arange(n)
    r2d = (n-1)*r[:,None]
    return ne.evaluate('r2d+r+1')

利用切片技术,我们的存储效率更高-

def ranged_mat_v4(n):
    r  = np.arange(n+1)
    r0 = r[1:]
    r1 = r[:-1,None]*(n-1)
    return ne.evaluate('r0+r1')

计时-

In [423]: %timeit ranged_mat(10000)
273 ms ± 3.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [424]: %timeit ranged_mat_v2(10000)
316 ms ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [425]: %timeit ranged_mat_v3(10000)
176 ms ± 85.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [426]: %timeit ranged_mat_v4(10000)
154 ms ± 82.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

还有np.from函数如下所示。docs here

def func(n):
    return np.fromfunction(lambda r,c: (n-1)*r+1+c, shape=(n,n))

它采用一个函数,该函数根据索引值计算数组。你知道吗

相关问题 更多 >