MATLAB:时间序列的n分钟/小时/天平均值



这是我之前在这里发布的一个问题的后续。根据Oleg Komarov的回答,我编写了一个小工具,使用accumarray()和datevec()的输出结构来获取每日、每小时等数据的平均值或总和。请随意在这里看一看(它可能写得不太好,但对我有用)。

我现在想做的是添加计算n分钟、n小时、n天等统计数据的功能,而不是像我的函数那样计算1分钟、1小时、1天等。我有一个粗略的想法,它只是在我的时间向量t上循环(如果我没有学习漂亮的accumarray(),这几乎是我已经做过的),但这意味着我必须做大量的错误检查,以查找数据间隙、不均匀的采样时间等。

我想知道是否有一种更优雅/高效的方法可以让我重用/扩展上面发布的旧函数,即仍然使用accumarray()和datevec()的方法,因为这使得处理间隙变得非常容易。

你可以在这里下载我最后一个问题的一些样本数据。这些样本是以30分钟的间隔采样的,所以我想做的一个可能的例子是计算6小时的平均值,而不依赖于它们没有间隙的假设和/或总是以精确的30分钟采样。


这就是我到目前为止所想到的,除了时间戳的一个小但容易解决的问题外,它运行得相当好(例如,0:30代表从0:30到0:45的时间间隔——不过,我的旧函数也遇到了同样的问题):

[…请参阅下面的答案…]

感谢木屑的启发。

如果您从没有任何间隙的均匀间隔测量开始,那么使用accumarray的链接方法对我来说似乎过于复杂。在我的私人工具箱中,我有以下函数用于计算向量的N点平均值:

function y = blockaver(x, n)
% y = blockaver(x, n)
% input points are averaged over n points
% always returns column vector
if n == 1
    y = x(:);
else
    nblocks = floor(length(x) / n);
    y = mean(reshape(x(1:n * nblocks), n, nblocks), 1).';
end

对于因子N的快速和脏抽取,效果非常好,但请注意,它没有应用适当的反别名过滤。如果这很重要,请使用decimate

我想我是用@Bas-Swinckels答案的一部分和上面链接的@woodchip的代码找到的。这并不完全是我所说的好代码,但工作起来相当快。

function [ t_acc, x_acc, subs ] = ts_aggregation( t, x, n, target_fmt, fct_handle )
% t is time in datenum format (i.e. days)
% x is whatever variable you want to aggregate
% n is the number of minutes, hours, days
% target_fmt is 'minute', 'hour' or 'day'
% fct_handle can be an arbitrary function (e.g. @sum)
    t = t(:);
    x = x(:);
    switch target_fmt
        case 'day'
            t_factor = 1;
        case 'hour'
            t_factor = 1 / 24;
        case 'minute'
            t_factor = 1 / ( 24 * 60 );
    end
    t_acc = ( t(1) : n * t_factor : t(end) )';
    subs = ones(length(t), 1);
    for i = 2:length(t_acc)
       subs(t > t_acc(i-1) & t <= t_acc(i)) = i; 
    end
    x_acc = accumarray( subs, x, [], fct_handle );
end

/edit:更新到一个更短的fnction,它确实使用了循环,但似乎比我以前的解决方案更快。

最新更新