Python 1d N阵列上切片的平均值:如何使其更具NumPy thonic?
作为我正在运行的一些模拟的一部分,我最终需要对一些非常长的(实数)序列执行以下操作。要点如下: 给定一个长的一维NumPy数组,对于数组中的每个位置,我想对该位置前后的值求平均值,取平均值之间的差值,并将这些差值加载到与原始数组相同维度的另一个nparray中 这是我的尝试。它工作得非常好,只是随着序列变长,速度会变得非常慢Python 1d N阵列上切片的平均值:如何使其更具NumPy thonic?,python,arrays,numpy,Python,Arrays,Numpy,作为我正在运行的一些模拟的一部分,我最终需要对一些非常长的(实数)序列执行以下操作。要点如下: 给定一个长的一维NumPy数组,对于数组中的每个位置,我想对该位置前后的值求平均值,取平均值之间的差值,并将这些差值加载到与原始数组相同维度的另一个nparray中 这是我的尝试。它工作得非常好,只是随着序列变长,速度会变得非常慢 将numpy导入为np def测试顺序(npseq): n=npseq.形状[0] 定义f(i): pre=np.和(npseq[:i])/i post=np.和(npse
将numpy导入为np
def测试顺序(npseq):
n=npseq.形状[0]
定义f(i):
pre=np.和(npseq[:i])/i
post=np.和(npseq[(i+1):])/(n-i)
回邮
out=np.数组([f(i)表示范围(1,n)中的i)])
返回
看起来很简单。但是
In [26]: a = np.random.randint(0,100,100000)
In [27]: %timeit example.test_sequence(a)
1 loops, best of 3: 7.69 s per loop
In [17]: a = np.random.randint(0,100,400000)
In [18]: %timeit example.test_sequence(a)
1 loops, best of 3: 1min 50s per loop
我知道可能有一种聪明的方法可以将其矢量化,但我对NumPy缺乏经验。谁能给我指出正确的方向吗
编辑:我最初写的是“总和”而不是“平均值”。我的意思是“平均值”。我的错。我知道这里可能有一个一个接一个的错误——我现在不担心。实际的问题比我在这里介绍的版本稍微复杂一些,所以无论如何我都需要处理它。这里有一种方法使用
np.cumcum()
:
np.cumsum()
将生成上一项的总和,a[::-1])[:-1]
是下一项的总和。因此,如果要计算平均值,则下一个项目的长度将为np.arange(a.size,1,-1)
,而上一个项目的长度将为np.arange(1,a.size)
,因此您可以执行以下操作:
np.cumsum(a[::-1])[::-1]/np.arange(a.size + 1, 1, -1) - np.cumsum(a)/np.arange(1, a.size + 1)
演示:
作为替代方案,您也可以使用pandas中的(即将弃用的)
expansing\u mean
功能:
import pandas as pd
a = np.array([32, 69, 79, 34, 1, 77, 54, 42, 73, 75])
pd.expanding_mean(a)[:-2:] - pd.expanding_mean(a[::-1])[-3::-1]
这里的输出匹配(我认为)函数的固定版本,但如果出现off by one错误,您可以按照自己的意愿进行修复:
def test_sequence(npseq):
n = npseq.shape[0]
def f(i):
pre = np.sum(npseq[:i])/i
post = np.sum(npseq[(i+1):])/(n-i-1)
return pre-post
out = np.array([f(i) for i in range(1,n-1)])
return out
test_sequence(a)
array([-22.375 , -0.35714286, 6.33333333, -10.7 ,
-18. , -14.66666667, -24.57142857, -26.5 ])
新的替换版本应使用扩展和平均值:
pd.Series(a[:-2:]).expanding().mean() - pd.Series(a[::-1]).expanding().mean()[-3::-1].reset_index(drop = True)
0 -22.375000
1 -0.357143
2 6.333333
3 -10.700000
4 -18.000000
5 -14.666667
6 -24.571429
7 -26.500000
dtype: float64
还有一些时机:
a = np.random.randint(0,100,100000)
%timeit test_sequence(a)
%timeit pd.Series(a[:-2:]).expanding().mean() - pd.Series(a[::-1]).expanding().mean()[-3::-1].reset_index(drop = True)
1 loop, best of 3: 8.17 s per loop
10 loops, best of 3: 18.5 ms per loop
看起来可能会加快速度。您的代码与您的描述不匹配。看起来您试图用平均值而不是求和来做一些事情,但是如果
post
应该是平均值,那么它很可能是一个一个的错误。是的,使用np.mean作为平均值以避免一个错误。@user2357112:这是一个打字错误。我是说一般。道歉!而且我也不太担心一个错误造成的后果。我最感兴趣的是如何将这种操作矢量化。
pd.Series(a[:-2:]).expanding().mean() - pd.Series(a[::-1]).expanding().mean()[-3::-1].reset_index(drop = True)
0 -22.375000
1 -0.357143
2 6.333333
3 -10.700000
4 -18.000000
5 -14.666667
6 -24.571429
7 -26.500000
dtype: float64
a = np.random.randint(0,100,100000)
%timeit test_sequence(a)
%timeit pd.Series(a[:-2:]).expanding().mean() - pd.Series(a[::-1]).expanding().mean()[-3::-1].reset_index(drop = True)
1 loop, best of 3: 8.17 s per loop
10 loops, best of 3: 18.5 ms per loop