对不同长度时间序列进行平均

0 投票
4 回答
1881 浏览
提问于 2025-04-18 09:37

我有一些列表(时间序列数据)

dictionary = {'a': [1,2,3,4,5], 'b': [5,2,3,4,1], 'c': [1,3,5,4,6]}

我想要在另一个列表上计算它们的平均值:

merged = {'m': [2.33,2.33,3.66,4.0,4.0]}

有没有什么聪明的方法可以做到这一点?

如果这些列表的长度不一样,我想要么从现有的数据中计算平均值,要么假装所有列表的数据都是在同一个时间段内产生的,尽管它们的数据点数量不同,这该怎么做呢?

4 个回答

0

一个简单的方法来处理好看的数据就是

from statistics import mean

dictionary = {'a': [1,2,3,4,5], 'b': [5,2,3,4,1], 'c': [1,3,5,4,6]}
merged = {'m': [mean(values) for values in zip(*dictionary.values())]}

merged
#>>> {'m': [2.3333333333333335, 2.3333333333333335, 3.6666666666666665, 4.0, 4.0]}

如果你用的是旧版的Python 3,可以把 statistics.mean 替换成 sum(values) / len(values)。如果你用的是Python 2,你需要加上 from __future__ import division,或者使用 float(len(values)

如果你想要线性插值,这也很简单:

from statistics import mean
import numpy

dictionary = {'a': [1,2,3,4,5], 'b': [5,2,3,1], 'c': [1,3,5,4,6]}

def interpolate_many(lists):
    maxlen = max(map(len, lists))
    interpolation_target = numpy.linspace(0, 1, maxlen)

    for lst in lists:
        x_values = numpy.linspace(0, 1, len(lst))
        yield numpy.interp(interpolation_target, x_values, lst)

interpolated = interpolate_many(dictionary.values())

merged = {'m': [mean(values) for values in zip(*interpolated)]}
merged
#>>> {'m': [2.3333333333333335, 2.5833333333333335, 3.5, 3.5, 4.0]}

这些操作的目的就是先处理一下列表,让短的列表拉伸到最大长度(maxlen,你可以根据需要更改这个值)。然后它会运行之前的代码。

0

下面的代码是根据找到的元素数量来计算数组的平均值。

dictionary = {'a': [1,2,3,4,5], 'b': [5,2,3,4,1], 'c': [1,3,5,4,6]}

mergerd = {'m': []}

i = 0
count = 0
num = len(dictionary)

while True:
    mergerd['m'].append(0)
    for key in dictionary: #for each entry in the dictionary
        if (len(dictionary[key]) <= i): #if the list for that entry doesn't have a element
            continue
        mergerd['m'][i] += dictionary[key][i]
        count += 1
    if count == 0: #if there were no more elements
        mergerd['m'].pop()
        break
    mergerd['m'][i] = mergerd['m'][i]/count
    count = 0
    i += 1

print(mergerd['m'])

运行后会产生以下输出结果

[2.3333333333333335, 2.3333333333333335, 3.6666666666666665, 4.0, 4.0]

if dictionary was equal to {'a': [1,2,3,4,5,3], 'b': [5,2,3,4,1,1,1], 'c': [1,3,5,4,6]}
# then the following would be output
[2.3333333333333335, 2.3333333333333335, 3.6666666666666665, 4.0, 4.0, 2.0, 1.0]

合并数组的最后两个元素是2.0和1.0

2是这样算出来的:只有两个数组有第六个元素,它们的值分别是3和1,所以(3+1)/2 = 2

1是这样算出来的:只有一个数组有第七个元素,那个值是1,所以1/1 = 1

0

你可以使用一个简单的列表推导式:

import numpy
dictionary = {'a': [1,2,3,4,5], 'b': [5,2,3,4,1], 'c': [1,3,5,4,6]}
vals = [dictionary.values()[i][j] for j in range(5) for i in range(3)]
vals = [vals[i:i+3] for i in range(0, len(vals), 3)]
merged = {}
merged['m'] = [numpy.mean(item) for item in vals)]
print merged #{'m': [2.3333333333333335, 2.3333333333333335, 3.6666666666666665, 4.0, 4.0]}
2

因为你在问题中提到了numpy和scipy,我猜测你是想用科学计算的Python函数。要完成第一个任务,有一个简单的方法如下:

$ ipython --pylab
>>> dictionary = {'a': [1,2,3,4,5], 'b': [5,2,3,4,1], 'c': [1,3,5,4,6]}
>>> map(mean, np.array(dictionary.values()).transpose())
[2.3333333333333335, 2.3333333333333335, 3.6666666666666665, 4.0, 4.0]

当然,你可以把这个结果放进一个字典里,使用键'm',然后把结果四舍五入,这样就能得到你想要的格式。

至于如何处理缺失值或者不同长度的数组,你首先需要决定缺失的数据该怎么处理。你问的第二个问题感觉有点模糊。

撰写回答