【问题标题】:numpy array fromfunction using each previous value as input, with non-zero initial valuenumpy 数组 fromfunction 使用每个先前的值作为输入,初始值非零
【发布时间】:2018-09-01 05:23:55
【问题描述】:

我想用一个函数来填充一个 numpy 数组。我希望数组以一个初始值开始并填充到给定长度,使用数组中的每个先前值作为函数的输入。

每个数组值 i 应该是 (i-1)*x**(y/z)。

经过一番努力,我必须:

import numpy as np
f = np.zeros([31,1])
f[0] = 20
fun = lambda i, j: i*2**(1/3)
f[1:] = np.fromfunction(np.vectorize(fun), (len(f)-1,1), dtype = int)

这会用

填充数组

[firstvalue=20, 0, i-1 + 1*2**(1/3),...]

我已经阅读到这里

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.fromfunction.html

Use of numpy fromfunction

Most efficient way to map function over numpy array

Fastest way to populate a matrix with a function on pairs of elements in two numpy vectors?

How do I create a numpy array using a function?

但我只是不知道如何将其转换为我的函数。

【问题讨论】:

  • 向我们展示如何使用迭代进行计算。正如我的回答所示(和您的链接)fromfunction 并不能帮助您执行迭代代码。它只是将该函数应用于整个索引集(使用 1 次调用)。 vectorize 也没有帮助。这只是将多个数组广播到只接受标量的函数的一种便捷方式。这些都不能保证速度。
  • 谢谢,我今天醒来时意识到,这种类型的操作不可能向量化,因为它会违反因果关系;该函数在计算出第 i-1 个值之前无法知道它是什么,因此它必须是一系列(迭代)运算来计算 i 的下一个值。我觉得非常愚蠢。我将尝试对其进行迭代并重新发布。
  • for i in np.linspace(1,len(f)-1,len(f)-1, dtype=int): f[i] = f[i-1]*2**(1/3)
  • 看起来不是很pythonic,更像是matlabby,但这就是我来自的地方......
  • 迭代非常pythonic;这就是列表的处理方式。 MATLAB 过去需要与numpy 相同的“矢量化”;但他们已经添加了jit 编译,这减少了从整个数组的角度思考的需要。 ``numba` 和 cython 可以达到相同的效果。

标签: python arrays function numpy


【解决方案1】:

除了最初的 20 之外,这会产生相同的值

np.arange(31)*2**(1/3)

您的迭代版本(稍作修改)

def foo0(n):
    f = np.zeros(n)
    f[0] = 20
    for i in range(1,n): 
        f[i] = f[i-1]*2**(1/3)
    return f

另一种选择:

def foo1(n):
    g = [20]
    for i in range(n-1):
        g.append(g[-1]*2**(1/3))
    return np.array(g)

它们产生相同的东西:

In [25]: np.allclose(foo0(31), foo1(31))
Out[25]: True

我的有点快:

In [26]: timeit foo0(100)
35 µs ± 75 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [27]: timeit foo1(100)
23.6 µs ± 83.6 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

但我们不需要每次都评估2**(1/3)

def foo2(n):
    g = [20]
    const = 2**(1/3)
    for i in range(n-1):
        g.append(g[-1]*const)
    return np.array(g)

节省少量时间。但这只是将每个条目乘以相同的常量。所以我们可以使用cumprod 来节省更多时间:

def foo3(n):
    g = np.ones(n)*(2**(1/3))
    g[0]=20
    return np.cumprod(g)

In [37]: timeit foo3(31)
14.9 µs ± 14.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [40]: np.allclose(foo0(31), foo3(31))
Out[40]: True

【讨论】:

  • 谢谢,但是即使第一个值是20,这也不会使用第i-1个值来计算i。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 2020-02-27
相关资源
最近更新 更多