计算MATLAB中时间序列数据的每周(或每月)平均值

时间:2016-03-14 10:17:20

标签: matlab time-series

假设我们在MATLAB R2015b中有DT_vec

DT_vec = 
2008    7   21  0   0   0
2008    7   22  0   0   0
2008    7   23  0   0   0
2008    7   29  0   0   0
2008    8   4   0   0   0
2008    8   12  0   0   0
2008    9   14  0   0   0
2008    9   15  0   0   0
2008    9   16  0   0   0
2008    9   17  0   0   0
2008    9   20  0   0   0
2008    9   21  0   0   0

存储在My_data中的数据:

32
43
12
43
2
12
54
32
34
5
32
12

我想要计算此时间序列的每周(或每月)平均值(My_data)。我怎么能这样做?

1 个答案:

答案 0 :(得分:4)

每月更容易,您可以使用DT_vec中的第一列和第二列来创建accumarray所需的subs数组

[~,~,subs] = unique(DT_vec(:,1:2), 'rows')
MonthlyMeans = accumarray(subs, My_data, [], @mean)

你可以每周做同样的事情,但是你必须弄清楚如何获得subs。它不应该复杂得多,但使用日期序列号(即datenum(DT_vec))可能更容易,然后执行subs = floor((datenum(DT_vec) + offset)/7)之类的操作,其中offset06之间的整数,用于获取周日(或周一)开始的数字。然后,您可能希望减去第一周的开始时间为1 subs = subs - min(subs) + 1

修改:这是如何运作的,offset是什么?

这里的想法是将您的日期表示为serial numbers (by using the datenum function)。来自datenum的文档:

  

datenum函数创建一个数字数组,表示每个时间点为从0000年1月0日起的天数。

因此,datenum的结果中的每个整数都代表一整天。在您的示例DT_vec(即datenum(DT_vec))上运行此操作,我们得到:

DT_num =

     733610
     733611
     733612
     733618
     733624
     733632
     733665
     733666
     733667
     733668
     733671
     733672

您的前两个日期是连续的,因此DT_num(2) - DT_num(1) == 1。那么我们如何找到周?我们需要将这些序列日期编号分组为7.为此,我将每个数字除以7,然后使用floor删除小数点。要使用较小的数字来证明这一点,当我们将0:14除以7时会发生什么?我们得到

     0
0.1429
0.2857
0.4286
0.5714
0.7143
0.8571
1.0000
1.1429
1.2857
1.4286
1.5714
1.7143
1.8571
2.0000

如果我们使用楼层删除小数,我们得到:

 0
 0
 0
 0
 0
 0
 0
 1
 1
 1
 1
 1
 1
 1
 2

您的实际数字也会出现同样的情况,他们只是从0开始。那么偏移量是多少?好吧,因为在除以7之后每个整数的变化代表一个新的星期,我们需要确保我们从周日开始划分周,而不是像星期四那样任意一天。由于MATLAB从1月1日开始计算,我们需要知道一周中的哪一天,然后使用offset来使它好像从下一个星期日开始计算。什么日子是0000年1月1日?我们可以使用MATLAB的weekday函数来查找。例如今天是星期几?

weekday(datenum([2016 03 14]))

返回2表示星期一。那天是哪一天0weekday(0)返回6表示星期五。因此,我们需要抵消此计数器,使其从0开始,因此offset应该等于weekday(1) - 1

为了进一步说明这一点,请考虑过去14天:

d = (today-7:today)'

现在

[floor(d/7) weekday(d)]

返回

ans =

  105198           2
  105198           3
  105198           4
  105198           5
  105199           6
  105199           7
  105199           1
  105199           2
  105199           3
  105199           4
  105199           5
  105200           6
  105200           7
  105200           1
  105200           2

当第二列从7转到1时,新的一周开始,但您可以看到第1列中由floor(d/7)创建的分组与此不对应。事实上它已被5(或-2)关闭。这就是我们想要使用offset的内容。因此,如果我们设置offset = weekday(0) - 1,那么

[floor((d+offset)/7) weekday(d)]

给出

  105199           2
  105199           3
  105199           4
  105199           5
  105199           6
  105199           7
  105200           1
  105200           2
  105200           3
  105200           4
  105200           5
  105200           6
  105200           7
  105201           1
  105201           2

正确划分周数。