在pandas.Series中容易找到大小为k的窗口中每个第n个元素的平均值的方法? (不是滚动的意思)

时间:2016-05-23 08:29:25

标签: python arrays numpy pandas

这里的动机是采用时间序列并在整个子时段(日,周)内获得平均活动。

可以重新整形数组并取y轴上的均值来实现这一点,类似于这个答案(但使用轴= 2):

Averaging over every n elements of a numpy array

但是我正在寻找可以处理长度为N%k!= 0的数组并且不能通过使用1或0重新整形和填充(例如numpy.resize)来解决问题,即取平均值仅限现有数据。

E.g以长度为N = 10的序列[2,2,3,2,2,3,2,2,3,6]开始,该序列不能被k = 3整除。我想要的是采用具有不匹配尺寸的重新形成阵列的平均值:

In: [[2,2,3], [2,2,3], [2,2,3], [6]], k =3

Out: [3,2,3]

而不是:

In: [[2,2,3], [2,2,3], [2,2,3], [6,0,0]], k =3

Out: [3,1.5,2.25]

谢谢。

3 个答案:

答案 0 :(得分:3)

您可以使用蒙版数组来填充查找均值时忽略的特殊值,而不是求和。

k = 3

# how long the array needs to be to be divisible by 3
padded_len = (len(in_arr) + (k - 1)) // k * k

# create a np.ma.MaskedArray with padded entries masked
padded = np.ma.empty(padded_len)
padded[:len(in_arr)] = in_arr
padded[len(in_arr):] = np.ma.masked

# now we can treat it an array divisible by k:
mean = padded.reshape((-1, k)).mean(axis=0)

# if you need to remove the masked-ness
assert not np.ma.is_masked(mean), "in_arr was too short to calculate all means"
mean = mean.data

答案 1 :(得分:2)

你可以轻松地通过填充,重新整形和计算每行划分的元素来实现

>>> import numpy as np
>>> a = np.array([2,2,3,2,2,3,2,2,3,6])
>>> k = 3

填充数据

>>> b = np.pad(a, (0, k - a.size%k), mode='constant').reshape(-1, k)
>>> b
array([[2, 2, 3],
       [2, 2, 3],
       [2, 2, 3],
       [6, 0, 0]]) 

然后创建一个面具:

>>> c = a.size // k # 3
>>> d = (np.arange(k) + c * k) < a.size # [True, False, False]

d的第一部分将创建一个包含[9, 10, 11]的数组,并将其与a(10)的大小进行比较,生成提到的布尔掩码。

除以它:

>>> b.sum(0) / (c + 1.0 * d)
array([ 3.,  2.,  3.])

以上将第一列除以4(c + 1 * True),其余为3。这是矢量化numpy,因此,它可以很好地扩展到大数组。

所有内容都可以写得更短,我只是展示了让它更清晰的所有步骤。

答案 2 :(得分:1)

通过解压缩链接展开列表In。创建一个新列表,按列排列展平列表lst,然后使用map函数计算每列的平均值:

from itertools import chain

In = [[2, 2, 3], [2, 2, 3], [2, 2, 3], [6]]

lst = chain(*In)
k = 3

In_by_cols = [lst[i::k] for i in range(k)]
# [[2, 2, 2, 6], [2, 2, 2], [3, 3, 3]]

Out  = map(lambda x: sum(x)/ float(len(x)), In_by_cols)
# [3.0, 2.0, 3.0]

在每个子列表的长度上使用float将在python 2.x上提供更准确的结果,因为它不会进行整数截断。