这是我之前发布的here问题的后续行动。基于Oleg Komarov的回答,我写了一个小工具来获取每日,每小时等平均值或使用accumarray()和datevec()输出结构的数据总和。请随意查看here(它可能写得不是很好,但它对我有用)。
我现在要做的是添加计算n分钟,n小时,n天等统计数据的功能,而不是像我的功能那样1分钟,1小时,1天等等。确实。我有一个粗略的想法,简单地循环我的时间向量t(这将是我已经做过的,如果我没有了解美丽的accumarray()),但这意味着我必须做很多错误检查数据间隙,采样时间不均等等。
我想知道是否有一种更优雅/更有效的方法可以让我重复使用/扩展上面发布的旧功能,即仍然使用accumarray()和datevec()的东西,因为这样可以很好地处理间隙容易。
您可以下载我上一期here中提取的一些示例数据。这些是以30分钟的间隔进行采样的,所以我想要做的一个可能的例子就是计算6小时平均值,而依赖于假设它们没有间隙和/或总是在30分钟。
这是我到目前为止所提出的,除了一个很小但很容易修复的时间戳问题之外,它运作得相当好(例如0:30代表0:30到0:45之间的间隔 - - 虽然我的旧函数遇到了同样的问题:
[...请参阅下面的答案...]
感谢woodchips获取灵感。
答案 0 :(得分:2)
使用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
。
答案 1 :(得分:1)
我想我用@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:更新为使用循环的更短的功能,但似乎比我以前的解决方案更快。