以一维向量为例,例如[a b c d].

然后构建以下矩阵

a    0   0  0
ab   b   0  0
abc  bc  c  0
abcd bcd cd d

到目前为止,我得到的代码完成了这项工作,但它很丑,并且有一个完全不必要的for循环.

import numpy as np

v = np.array([1, 2, 3])
n = len(v)
matrix = np.zeros((n,n))
for i in range(n):
    matrix [i,:i+1] = np.flip(np.cumprod(np.flip(v[:i+1])))

print(matrix)
# [[1. 0. 0.]
#  [2. 2. 0.]
#  [6. 6. 3.]]

我如何将其矢量化?

推荐答案

If speed is concern you can consider using :

from numba import njit

@njit
def cumprod_triangular_numba(arr):
    out = np.zeros((arr.size, arr.size), dtype=np.int64)

    for col in range(arr.size):
        p = 1
        for row in range(col, arr.size):
            p *= arr[row]
            out[row, col] = p

    return out

基准:

import numpy as np
import perfplot
from numba import njit, prange
from numpy.lib.stride_tricks import sliding_window_view


def cumprod_triangular_orig(arr):
    n = len(arr)
    matrix = np.zeros((n, n))
    for i in range(n):
        matrix[i, : i + 1] = np.flip(np.cumprod(np.flip(arr[: i + 1])))
    return matrix


def cumprod_triangular_james(arr):
    return sum(
        np.diagflat(sliding_window_view(arr, i + 1).prod(axis=1), -i)
        for i in range(len(arr))
    )


def cumprod_triangular_onyambu_1(arr):
    u = arr.cumprod()
    return u[:, None] / np.r_[1, u[:-1]] * np.tri(arr.size, dtype=int)


def cumprod_triangular_onyambu_2(arr):
    a = np.triu(arr).T
    i1 = a == 0
    a[i1] = 1
    return np.where(i1, 0, a.cumprod(0))


def cumprod_triangular_onyambu_3(arr):
    a = np.triu(arr).T
    return np.where(a, a, 1).cumprod(0) * np.tri(arr.size, dtype=int)


@njit
def cumprod_triangular_numba(arr):
    out = np.zeros((arr.size, arr.size), dtype=np.int64)

    for col in prange(arr.size):
        p = 1
        for row in range(col, arr.size):
            p *= arr[row]
            out[row, col] = p

    return out


@njit(parallel=True)
def cumprod_triangular_numba_parallel(arr):
    out = np.zeros((arr.size, arr.size), dtype=np.int64)

    for col in prange(arr.size):
        p = 1
        for row in range(col, arr.size):
            p *= arr[row]
            out[row, col] = p

    return out


arr = np.array([2, 3, 5, 7])

assert np.allclose(cumprod_triangular_numba(arr), cumprod_triangular_orig(arr))
assert np.allclose(cumprod_triangular_numba_parallel(arr), cumprod_triangular_orig(arr))
assert np.allclose(cumprod_triangular_james(arr), cumprod_triangular_orig(arr))
assert np.allclose(cumprod_triangular_onyambu_1(arr), cumprod_triangular_orig(arr))
assert np.allclose(cumprod_triangular_onyambu_2(arr), cumprod_triangular_orig(arr))
assert np.allclose(cumprod_triangular_onyambu_3(arr), cumprod_triangular_orig(arr))


np.random.seed(0)

perfplot.show(
    setup=lambda n: np.random.randint(1, 2, size=n, dtype=np.int64),
    kernels=[
        cumprod_triangular_orig,
        cumprod_triangular_james,
        cumprod_triangular_numba,
        cumprod_triangular_numba_parallel,
        cumprod_triangular_onyambu_1,
        cumprod_triangular_onyambu_2,
        cumprod_triangular_onyambu_3,
    ],
    labels=["orig", "james", "numba", "numba_parallel", "o_1", "o_2", "o_3"],
    n_range=[3, 5, 10, 15, 20, 25, 50, 75, 100, 200, 500, 1000],
    xlabel="N",
    logx=True,
    logy=True,
    equality_check=np.allclose,
)

在我的计算机(AMD 5700x)上创建此图:

enter image description here

Python相关问答推荐

如何在图片中找到这个化学测试条?OpenCV精明边缘检测不会绘制边界框

线性模型PanelOLS和statmodels OLS之间的区别

类型错误:输入类型不支持ufuncisnan-在执行Mann-Whitney U测试时[SOLVED]

为什么这个带有List输入的简单numba函数这么慢

将tdqm与cx.Oracle查询集成

使用NeuralProphet绘制置信区间时出错

转换为浮点,pandas字符串列,混合千和十进制分隔符

考虑到同一天和前2天的前2个数值,如何估算电力时间序列数据中的缺失值?

使用BeautifulSoup抓取所有链接

交替字符串位置的正则表达式

Cython无法识别Numpy类型

如何使用正则表达式修改toml文件中指定字段中的参数值

Python pint将1/华氏度转换为1/摄氏度°°

如何在Gekko中使用分层条件约束

没有内置pip模块的Python3.11--S在做什么?

在第一次调用时使用不同行为的re. sub的最佳方式

Python日志(log)库如何有效地获取lineno和funcName?

无法使用请求模块从网页上抓取一些产品的名称

利用广播使减法更有效率

如何通过函数的强式路径动态导入函数?