numpy 函数来聚合时间信号?

Posted

技术标签:

【中文标题】numpy 函数来聚合时间信号?【英文标题】:numpy function to aggregate a signal for time? 【发布时间】:2012-05-30 12:31:09 【问题描述】:

我想计算某个时间段内某个信号的聚合平均值。我不知道这在科学上是怎么称呼的。

示例:我以 15 分钟的值计算一整年的用电量。我想知道我一天中每小时的平均消耗量(24 个值)。但它更复杂:在 15 分钟的步骤之间有更多的测量值,我无法预测它们在哪里。但是,应该考虑它们,并使用正确的“重量”。

我写了一个可以工作的函数,但是它非常慢。这是一个测试设置:

import numpy as np

signal = np.arange(6)
time = np.array([0, 2, 3.5, 4, 6, 8])
period = 4
interval = 2

def aggregate(signal, time, period, interval):
    pass

aggregated = aggregate(signal, time, period, interval)
# This should be the result: aggregated = array([ 2.   ,  3.125])

aggregated 应该有 period/interval 值。这是手动计算:

aggregated[0] = (np.trapz(y=np.array([0, 1]), x=np.array([0, 2]))/interval + \
               np.trapz(y=np.array([3, 4]), x=np.array([4, 6]))/interval) / (period/interval)
aggregated[1] = (np.trapz(y=np.array([1, 2, 3]), x=np.array([2, 3.5, 4]))/interval + \
                np.trapz(y=np.array([4, 5]), x=np.array([6, 8]))/interval) / (period/interval)

最后一个细节:它必须高效,这就是为什么我自己的解决方案没有用。也许我忽略了一个 numpy 或 scipy 方法?或者这是熊猫可以做的事情吗? 非常感谢你的帮助。

【问题讨论】:

我觉得这很难理解。信号点出现时是time 值吗? periodinterval 值如何关联?而且我没有得到您的手动计算,所有interal 值都取消了。请尝试澄清一下:) 我尽量说清楚。我试图通过我给出的例子来澄清:time 值确实是信号发生的地方,让我们假设它以秒为单位。 period 将是 86400,interval 将是 3600。我希望这会有所帮助 酷,firstsecond 值代表什么? 这些是aggregated 元素的“物理”计算。这很混乱,但我想展示如何理解所需结果的实际含义。 【参考方案1】:

我根据之前的答案和 pandas 制定了一个完全符合我要求的函数。

def aggregate_by_time(signal, time, period=86400, interval=900, label='left'):
"""
Function to calculate the aggregated average of a timeseries by 
period (typical a day) in bins of interval seconds (default = 900s).

label = 'left' or 'right'.  'Left' means that the label i contains data from 
i till i+1, 'right' means that label i contains data from i-1 till i.    

Returns an array with period/interval values, one for each interval
of the period. 

Note: the period has to be a multiple of the interval

"""

def make_datetimeindex(array_in_seconds, year):
    """
    Create a pandas DateIndex from a time vector in seconds and the year.
    """

    start = pandas.datetime(year, 1, 1)
    datetimes = [start + pandas.datetools.timedelta(t/86400.) for t in array_in_seconds]

    return pandas.DatetimeIndex(datetimes)

interval_string = str(interval) + 'S'    
dr = make_datetimeindex(time, 2012)
df = pandas.DataFrame(data=signal, index=dr, columns=['signal'])
df15min = df.resample(interval_string, closed=label, label=label)

# now create bins for the groupby() method
time_s = df15min.index.asi8/1e9
time_s -= time_s[0]
df15min['bins'] = np.mod(time_s, period)

df_aggr = df15min.groupby(['bins']).mean()

# if you only need the numpy array: take df_aggr.values
return df_aggr 

【讨论】:

【参考方案2】:

我强烈推荐使用 Pandas。这里我使用的是 0.8 版(即将发布)。我认为这接近您想要的。

import pandas as p
import numpy as np
import matplotlib as plt

# Make up some data:
time = p.date_range(start='2011-05-23', end='2012-05-23', freq='min')
watts = np.linspace(0, 3.14 * 365, time.size)
watts = 38 * (1.5 + np.sin(watts)) + 8 * np.sin(5 * watts)

# Create a time series
ts = p.Series(watts, index=time, name='watts')

# Resample down to 15 minute pieces, using mean values
ts15 = ts.resample('15min', how='mean')
ts15.plot()

Pandas 可以利用您的数据轻松地做许多其他事情(例如确定您的平均每周能量状况)。查看 p.read_csv() 以读取您的数据。

【讨论】:

他将不得不为 pandas 0.8.0 的发布而坚持 这不是我需要的。 resample() 的结果与我想要的聚合不同。您的示例将产生 8640*4 值(一年,15 分钟间隔),而我想获得 24*4 值的结果(一年中所有日子的平均值为 15 分钟)。 pandas 0.8 有这个功能吗? @sarole 你想按一天 24 小时分组,分成 15 分钟增量的平均值吗? 我想是的。我想知道一年中所有日子在 00h00 和 00h15 之间的平均值是多少(所以每个时间间隔只有 1 个值)。这会给我 24*4 的值。 找到了我的问题的答案并编辑了这个答案以使其完全回答问题。【参考方案3】:

我认为这非常接近您的需要。我不确定我是否正确地解释了区间和周期,但我认为我是在某个常数因子内写的。

import numpy as np

def aggregate(signal, time, period, interval):
    assert (period % interval) == 0
    ipp = period / interval

    midpoint = np.r_[time[0], (time[1:] + time[:-1])/2., time[-1]]
    cumsig = np.r_[0, (np.diff(midpoint) * signal).cumsum()]
    grid = np.linspace(0, time[-1], np.floor(time[-1]/period)*ipp + 1)
    cumsig = np.interp(grid, midpoint, cumsig)
    return np.diff(cumsig).reshape(-1, ipp).sum(0) / period

【讨论】:

你的功能给我留下了深刻的印象,你教我高级 numpy 使用。我自己的函数有一个 while 和一个 for 循环,而你的函数要快很多数量级。非常感谢。 编辑:你的函数有问题。应用于具有不规则时间间隔的长数据序列时,我得到了错误的结果。我会尝试熊猫的方式。 我对 Pandas 不太熟悉,但如果它有你需要的东西,它可能会比尝试修复我的功能更容易、更强大。

以上是关于numpy 函数来聚合时间信号?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sqlalchemy 编写自己的聚合函数?

numpy通用函数

pandas 笔记:聚合函数agg

pandas agg函数使用方法

Numpy中的矩阵运算+聚合操作+arg运算(2019.1.17)

Numpy学习之