【问题标题】:Efficient Rolling Window Identification in MatlabMatlab 中的高效滚动窗口识别
【发布时间】:2011-02-17 22:29:24
【问题描述】:

我有一些缺失数据的时间序列数据,我在滚动窗口上运行一些估计函数。窗口的长度不统一,每个变量都有不同的开始日期和结束日期。我想删除任何缺少数据的窗口。窗口重叠,因此一个缺失的观察通常会从考虑中删除大量窗口。我想要的是从每个日期到包含它的窗口的映射。

目前,我有一个逻辑矩阵,其中每一天都有一行,然后每一列代表一个窗口,其中一个窗口在该窗口的日子里具有真实值。然后我可以将该矩阵子集为表示缺失数据的行,并且任何包含任何真实值的列都是无效窗口。问题是逻辑矩阵变得很大(10k x 10k ~100mb)并且可能有很多。我可以转换为解决大小问题的稀疏,但是当窗口很长时,计算要删除哪些窗口变得很慢。

这听起来不像是一个资源密集型问题(内存或计算),有没有更好的方法?

编辑:让我添加一个示例,这样可能会更清楚一点。假设完整的日期范围从 1 到 100。窗口是 1:10、2:11、3:12 等到 91:100(这些是统一的,但对于示例来说无关紧要)。我有一个从 5 到 25 的系列,但有 17 的 NaN。

一个 NaN 会敲掉十个窗口(8:17 到 17:26)。我想要一个从观察 17 到 Windows 8:17 的有效映射。显然,当窗口长度一致时,这很容易,但是当窗口不规则时,有什么有效的方法呢?

【问题讨论】:

  • 我不明白。 (date >= begin(i) && data < end(i)) 有什么问题(或不足)?您需要举例说明您打算如何使用这些信息。
  • @Oli 我添加了一个示例,希望能让事情更清楚。

标签: matlab


【解决方案1】:

逻辑比较花费很少的时间和资源。你确定这是一个瓶颈吗?

如果创建窗口很耗时,您可能希望在while 循环中进行,以便在窗口内遇到NaN 时可以跳过一些条目。

如果窗口创建速度很快,肯定是统一长度的,你可以这样做

%# startEnd is created according to your example, but can be whatever quick method
startEnd = [(1:(100-windowSize+1))',(windowSize+1:100)'];
nanIdx = find(isnan(data))';  %'#

%# This line temporarily creates a logical array of size nWindows-by-numberOfNaNs
%# which is most likely smaller than nWindows-by-nWindows
badWindows = any(bsxfun(@le,startEnd(:,1),nanIdx) & bsxfun(@ge,startEnd(:,2),nanIdx),2);

startEnd(badWindows,:) = [];

【讨论】:

  • 感谢您的回复。我曾想过这种方法 - 问题是我们最终会进行大量冗余的 isnan 检查(对它所在的每个窗口的每次观察,而不是每次观察一次)。如果每个窗口大约有 100 次观察,那么每次观察我们将检查(几乎)100 次。我想检查一次时间序列,然后将其映射到窗口中。
  • 这是瓶颈,我也对此感到惊讶。但是,我认为问题在于我将完整的矩阵细分为我拥有数据的行(示例中为 5:25)。我真的很喜欢您的解决方案,这是对 bsxfun 的一种优雅使用,并且在没有丢失数据的常见情况下应该非常有效。
  • 我对此进行了编码,有点令人惊讶的是,它变得更慢了,我认为是因为仍在检查所有可能的窗口中的每个丢失的数据点(而不是像我描述的方法那样索引) .我想出了我认为更好的方法,如下所述。
【解决方案2】:

我编写了 Jonas 的解决方案,结果它比我已有的解决方案要慢。然而,它确实消除了对大型阵列的需求,它让我以不同的方式思考这个问题。我只需要从一个窗口 ->(obs 开始,obs 结束)映射到一个 obs ->(obs 落入的每个窗口的索引)方法。

所以我构建了一个单元数组,其中包含每天的每组窗口索引(我可以使用 NumObsx2 矩阵,但我想允许可能复杂的窗口定义)。对于每个时间序列,我使用每个缺失数据点的索引对映射进行子集化,以获取所有需要删除的窗口的索引。然后 cell2mat 将索引从单元阵列中拉出,我可以删除坏窗口(谢天谢地,Matlab 不关心重复的索引)。

在我的计时中,这种方法大约是我原来方法的 10 倍,是 Jonas 方法的 15 倍。地图中的索引可以存储为 uint16,因此所需的内存远低于我的原始解决方案(但仍超过 Jonas 的方法)。

作为奖励,如果我想使用更复杂的标准,例如不超过 5 个 NaN(参见描述的不超过一个),我可以使用 accumarray 来计算索引。

【讨论】:

  • 有趣。顺便说一句,如果您将索引存储在 n×1 元胞数组 idxCell 中,调用 badWindows = cellfun(@(x)any(isnan(data(x))),idxCell) 会很快,还是会再次进行太多测试?
  • 我认为测试太多 - idxCell 的每个单元格都将包含该窗口数据的所有索引,因此您将检查每个窗口内的每个观察值的 isnan(而不仅仅是每个观察值) .另一方面,矢量化代码更漂亮...
猜你喜欢
  • 2019-01-31
  • 2013-01-27
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2013-11-12
  • 2011-01-13
  • 2012-09-20
  • 2016-06-22
相关资源
最近更新 更多