2015-08-20 39 views
0

给定一个将时间作为行索引的Deedle系列,我需要找到信号第一次满足条件的时间(在这种情况下,保持低于0.005,50ms) 。查找满足条件的第一个窗口

目前我拿一个50ms的移动窗口,并从每个窗口的开始时间和最大值创建一个序列,然后得到第一个,其最大值为< 0.005。它工作得很好,但可能效率很低。

// Assume a timestep of 1ms 
int numSteps = 50; 

// Create a series from the first index and max of each window 
var windowMaxes = mySeries.WindowInto(
    numSteps, 
    s => new KeyValuePair<double, double>(s.FirstKey(), s.Max())); 
var zeroes = windowMaxes.Where(kvp => kvp.Value <= 0.005); 

// Set to -1 if the condition was never satisfied 
var timeOfZero = zeroes.KeyCount > 0 ? zeroes.FirstKey() : -1D; 

的问题是,它搜索整个系列(这可能会变得非常大),即使第一窗口满足条件。

有没有简单的方法来做到这一点,但停止当第一个窗口被发现,而不是搜索整个系列?

回答

1

嗯,我无法找到一个Deedly一行程序或任何方便的LINQ命令来做到这一点,所以我写了下面的扩展方法:

public static K FirstWindowWhere<K, V>(
    this Series<K, V> series, 
    Func<V, bool> condition, 
    int windowSize) 
{ 
    int consecutiveTrues = 0; 
    foreach (var datum in series.Observations) 
    { 
     if (condition(datum.Value)) 
     { 
      consecutiveTrues++; 
     } 
     else 
     { 
      consecutiveTrues = 0; 
     } 

     if (consecutiveTrues == windowSize) 
     { 
      return datum.Key; 
     } 
    } 
    return default(K); 
} 

要与我的上述条件拨打:

double zeroTime = mySeries.FirstWindowWhere(d => d <= 0.005, numSteps); 

我尝试了几种不同的方法,包括使用Series.Between而不是Series.GetObservations的漂亮优雅的方法,但速度明显较慢。因此,除非有人有更简单/更好的解决方案,否则这样做。