0

给定一个以时间为行索引的 Deedle 系列,我需要找到信号首次满足条件的时间(在本例中,保持低于 0.005 50 毫秒)。

目前我采用一个 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;

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

有没有一种简单的方法可以做到这一点,但在找到第一个窗口时停止,而不是搜索整个系列?

4

1 回答 1

1

好吧,我找不到 Deedly one-liner 或任何方便的 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但它明显变慢了。因此,除非有人有更简单/更好的解决方案,否则这将是可行的。

于 2015-08-21T07:53:16.407 回答