我有一个数值积分的任务,其中我们用积分公式近似积分。我的问题是,任务需要我避免循环并使用矢量化变体,这将是一个切片?!
我有n个值的np.array对象,我必须使用特定的公式更改此数组的每个值。问题是这个数组在i点的值是在公式中用来改变位置的。用for循环很容易:
x = np.array([...])
for i in range(0,n):
x[i]=f(x[i]+a)*b`
(a,b一些其他变量) 我怎么用切片做这个?我必须为数组的所有元素执行此操作,因此它将类似于:
x[:]=f(x[???]+a)*b
我如何从我的阵列中获得正确的位置到公式?像x [:]之类的切片指令只是贯穿整个对象。有没有办法以某种方式保存我目前的索引? 我试图搜索但没有找到任何东西。另一个问题是我甚至不知道如何正确地提出搜索请求......
答案 0 :(得分:0)
你可能会混淆两个问题
在
x = np.array([...])
for i in range(0,n):
x[i]=f(x[i]+a)*b`
您逐个更改x
的元素,并将它们逐个传递给f
。
x[:] = ...
允许您同时更改x
的所有元素,但源(等式的右侧)必须生成所有这些值。但通常你不需要分配值。而只是使用x = ...
。它的速度和内存效率一样快。
在RHS上使用x[:]
对您没有任何帮助。如果x
是一个列表,则会复制该列表;如果x
是一个数组,则返回一个view
,一个具有相同值的数组。
关键问题是,f(...)
函数接受了什么?如果它使用+
,*
等操作以及np.sin
等函数,则可以为其指定数组,并返回数组。
但如果它仅适用于标量(包括使用math.sin
等函数),则必须为其添加标量,即x[i]
。
让我们尝试解开该评论(这可能会更好地作为对原始问题的修改)
我有一个必须在picies中削减的间隔。
x = np.linspace(start,end,pieceAmount)
function f
quadrature formula
b (weights or factors)
c (function values)
b1*f(x[i]+c1)+...+bn*f(x[i]+cn)
例如
In [1]: x = np.arange(5)
In [2]: b = np.arange(3)
In [6]: c = np.arange(4,7)*.1
我们可以通过广播为所有x[i]+c
和x
执行c
In [7]: xc = x + c[:,None]
In [8]: xc
Out[8]:
array([[ 0.4, 1.4, 2.4, 3.4, 4.4],
[ 0.5, 1.5, 2.5, 3.5, 4.5],
[ 0.6, 1.6, 2.6, 3.6, 4.6]])
如果f
是一个类似np.sin
的函数,它接受任何数组,我们可以将xc
传递给它,返回一个大小相同的数组。
再次通过广播我们可以进行b[n]*f(x[i]+c[n])
计算
In [9]: b[:,None]* np.sin(xc)
Out[9]:
array([[ 0. , 0. , 0. , -0. , -0. ],
[ 0.47942554, 0.99749499, 0.59847214, -0.35078323, -0.97753012],
[ 1.12928495, 1.99914721, 1.03100274, -0.88504089, -1.98738201]])
然后我们可以总结一下,找回一个像x
一样的数组:
In [10]: np.sum(_, axis=0)
Out[10]: array([ 1.60871049, 2.99664219, 1.62947489, -1.23582411, -2.96491212])
这是点或矩阵产品:
In [11]: b.dot(np.sin(xc))
Out[11]: array([ 1.60871049, 2.99664219, 1.62947489, -1.23582411, -2.96491212])
正如我之前提到的,我们可以用
完成动作x = b.dot(f(x+c[:,None])
像这样的简单表达式的关键是f
取一个数组。