Python 以矢量化方式创建给定大小的NumPy矩阵

Python 以矢量化方式创建给定大小的NumPy矩阵,python,numpy,vectorization,Python,Numpy,Vectorization,是否有内置NumPy函数或任何矢量化方法为n>1的值生成以下2D NumPy矩阵?让我举例说明n等于2、3和4的所需矩阵 一种方法是在下三角部分构造一个1的矩阵,然后简单地乘以一个向量np.arange(1,n+1)。还有其他选择吗 import numpy as np 用于n=2 用于n=3 用于n=4 我的尝试(示例为n=4)为循环使用嵌套的。它适用于n>1的任何值: import numpy as np n = 4 arr = np.zeros((n, n)) for i in r

是否有内置NumPy函数或任何矢量化方法为
n
>1的值生成以下2D NumPy矩阵?让我举例说明
n
等于2、3和4的所需矩阵

一种方法是在下三角部分构造一个1的矩阵,然后简单地乘以一个向量
np.arange(1,n+1)
。还有其他选择吗

import numpy as np
用于n=2

用于n=3

用于n=4


我的尝试(示例为
n=4
)为循环使用嵌套的
。它适用于
n
>1的任何值:

import numpy as np

n = 4
arr = np.zeros((n, n))

for i in range(n):
    for j in range(0, i+1):
        arr[i][j] = i+1 

# array([[1., 0., 0., 0.],
#        [2., 2., 0., 0.],
#        [3., 3., 3., 0.],
#        [4., 4., 4., 4.]])    

您可以使用
np.tril
np.broadcast\u to
创建初始
arange
变体

import numpy as np

n = 4
np.tril(np.broadcast_to(np.arange(1, n+1)[:, None], (n, n)))


下面是一个使用
np的解决方案。其中
和广播:

x = np.arange(1,n+1)
np.where(x[:,None]>=x,x[:,None],0)
# array([[1, 0, 0, 0],
#        [2, 2, 0, 0],
#        [3, 3, 3, 0],
#        [4, 4, 4, 4]])

我们可以使用远程阵列乘以下三角掩模-

In [44]: n = 5

In [45]: np.arange(1,n+1)[:,None]*np.tri(n,dtype=bool)
Out[45]: 
array([[1, 0, 0, 0, 0],
       [2, 2, 0, 0, 0],
       [3, 3, 3, 0, 0],
       [4, 4, 4, 4, 0],
       [5, 5, 5, 5, 5]])
考虑到面向算术的特性,它很容易移植到
numexpr
以利用多核处理大数据-

import numexpr as ne

ne.evaluate('A*B',{'A':np.arange(1,n+1)[:,None],'B':np.tri(n,dtype=bool)})
标杆管理 包括所有张贴在这里的解决方案

基准测试脚本-

import numpy as np
import perfplot

import numexpr as ne

def numexpr_range_broadcast(n):
    return ne.evaluate('A*B',{'A':np.arange(1,n+1)[:,None],'B':np.tri(n,dtype=bool)})

def where_method(n):
    x = np.arange(1,n+1)
    return np.where(x[:,None]>=x,x[:,None],0)

perfplot.show(
    setup=lambda n: n,
    kernels=[
        lambda n: where_method(n),
        lambda n: np.tril(np.broadcast_to(np.arange(1, n+1)[:, None], (n, n))),
        lambda n: np.arange(1,n+1)[:,None]*np.tri(n,dtype=bool),
        lambda n: numexpr_range_broadcast(n),
        ],
    labels=['where','tril_broadacast','range_broadcast','numexpr_range_broadcast'],
    n_range=[10, 20, 50, 80, 100, 200, 500, 800, 1000, 2000, 5000],
    xlabel='n',
    logx=True,
    logy=True,
    )
输出-

因此,在低于
n的
100的
np上,
np。基于
的一方赢得它,而在较大的
n的
上,
numexpr
闪耀

x = np.arange(1,n+1)
np.where(x[:,None]>=x,x[:,None],0)
# array([[1, 0, 0, 0],
#        [2, 2, 0, 0],
#        [3, 3, 3, 0],
#        [4, 4, 4, 4]])
In [44]: n = 5

In [45]: np.arange(1,n+1)[:,None]*np.tri(n,dtype=bool)
Out[45]: 
array([[1, 0, 0, 0, 0],
       [2, 2, 0, 0, 0],
       [3, 3, 3, 0, 0],
       [4, 4, 4, 4, 0],
       [5, 5, 5, 5, 5]])
import numexpr as ne

ne.evaluate('A*B',{'A':np.arange(1,n+1)[:,None],'B':np.tri(n,dtype=bool)})
import numpy as np
import perfplot

import numexpr as ne

def numexpr_range_broadcast(n):
    return ne.evaluate('A*B',{'A':np.arange(1,n+1)[:,None],'B':np.tri(n,dtype=bool)})

def where_method(n):
    x = np.arange(1,n+1)
    return np.where(x[:,None]>=x,x[:,None],0)

perfplot.show(
    setup=lambda n: n,
    kernels=[
        lambda n: where_method(n),
        lambda n: np.tril(np.broadcast_to(np.arange(1, n+1)[:, None], (n, n))),
        lambda n: np.arange(1,n+1)[:,None]*np.tri(n,dtype=bool),
        lambda n: numexpr_range_broadcast(n),
        ],
    labels=['where','tril_broadacast','range_broadcast','numexpr_range_broadcast'],
    n_range=[10, 20, 50, 80, 100, 200, 500, 800, 1000, 2000, 5000],
    xlabel='n',
    logx=True,
    logy=True,
    )