【问题标题】:Rolling-window matrix with different intervals between columns具有不同列间距的滚动窗口矩阵
【发布时间】:2018-06-22 23:07:44
【问题描述】:

我有一个包含 21 年每日数据的数据向量,并希望创建一个 365 天的滚动窗口,例如下一个周期在前一个周期之后一个月(30 天)出现。在问题中,n_interval 定义了下一个窗口的第一个数据点与上一个系列的最后一个观察值之间的差异。

假设我的每日数据从 2000 年 1 月 1 日开始,那么第一列将从 2000 年 1 月 1 日到 2001 年 1 月 1 日,第二列从 2000 年 2 月 1 日开始,到 2 月 1 日结束, 2001. and ... 最后一列将涵盖 2017 年 1 月 1 日至 2018 年 1 月 1 日。例如,如果:

vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]

对于给定变量n_interval = 3with window_size=5,输出矩阵应如下所示:

mat = [[1 4 7  10  13],
       [2 5 8  11  14],
       [3 6 9  12  15],
       [4 7 10 13  16],
       [5 8 11 14  17]]

【问题讨论】:

  • 抱歉,您能否阐明 n_interval 值的预期行为?不确定我是否理解这个问题!也许更多的源代码会有所帮助
  • 并非示例输出中的所有行都具有相同数量的元素(最后一个有 4 个,其余 5 个),因此您无法将其保存在矩阵中。你想让我做什么?以不同的格式保存还是用 NaN 填充?
  • 我不明白该示例与原始问题的对应关系。要重新创建示例,您可以使用以下可怕的一列 mat = vec(mod(bsxfun(@plus, 0:(k-1), (1:n:(numel(vec)-n+1))')-1,numel(vec))+1) 其中 n=3k=5 是列数。
  • 然后 jodag 上面的评论加上最后的转置就可以完成这项工作。或许可以简化为vec(bsxfun(@plus, 0:(k-1), (1:n:(numel(vec)-n+1))')).'
  • 我使用了一点voodoo 来得出numel(vec)-n+1 绑定。原来它只是因为nk 的特定值才起作用。我在回答中发布了一种更有原则的方法。

标签: matlab matrix vector sliding-window


【解决方案1】:

给定你的示例向量

vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17];

我们可以通过以下方式创建索引方案:

首先,我们需要确定mat 中有多少行。假设我们希望vec 的每个元素至少在mat 中表达一次,那么我们需要确保最后一行中的最后一个索引大于或等于vec 的大小。很容易看出mat 中最后一列的索引由

last_index = n_interval*(n_rows-1) + n_columns

我们要确保last_index >= numel(vec)。将上述表达式代入不等式并求解n_rows 得到

n_rows >= (numel(vec) - n_columns)/n_interval + 1

我们将n_rows 指定为该边界的ceil,使其成为满足不等式的最小整数。现在我们知道了行数,我们为每一行生成起始索引列表

start_index = 1:n_interval:(n_interval*(n_rows-1)+1);

在索引矩阵中,我们希望每一列都是 1 加上前一列。也就是说我们要根据数组index_offset = 0:(n_interval-1)来偏移列。

使用bsxfun,我们通过计算start_indexindex_offset 数组之间所有对的总和来生成索引矩阵

index = bsxfun(@plus, index_offset, start_index');

我们需要担心的最后一件事是越界。为了处理这个问题,我们应用mod 函数来包装越界索引:

index_wrapped = mod(index-1, numel(vec))+1;

然后我们简单的根据index_wrapped对向量进行采样

mat = vec(index_wrapped);

完整的代码是

n_interval = 3;
n_columns = 5;
vec = 1:17;

n_rows = ceil((numel(vec)-n_columns)/n_interval + 1);
start_index = 1:n_interval:(n_interval*(n_rows-1)+1);
index_offset = 0:(n_columns-1);
index = bsxfun(@plus, index_offset, start_index');
index_wrapped = mod(index-1, numel(vec))+1;
mat = vec(index_wrapped);

【讨论】:

  • 这是一个非常灵活的解决方案,
猜你喜欢
  • 2018-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
相关资源
最近更新 更多