我有一种方法可以计算时间序列的移动中值。就像移动平均值一样,它使用固定的窗口或周期(有时称为回顾期)。 如果周期为10,它将创建前10个值(0-9)的数组,然后查找它们的中值。它会重复这一步,将窗口递增1步(现在的值为1-10),等等......因此是这个的移动部分。这个过程与移动平均线完全相同。C#计算时间序列的移动中值SortedList <DateTime,double> - 提高性能?
中位值由实测值:
- 对数组排序
- 的值如果为奇数编号的数组中的值,取中间值。一个有5个值的排序数组的中值将是第3个值。
- 如果数组中有偶数个值,则取中间每一侧的两个值并对其进行平均。 6个值的排序后的数组的中值将是(第二+第三)/ 2。
我已经创建了通过填充一个List<double>
,主叫List<>.Sort()
,然后找到合适的值来计算这样的功能。
计算它是正确的,但我想知道是否有一种方法来提高此计算的性能。也许通过手动滚动double[]
而不是使用列表。
我实现如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Moving_Median_TimeSeries
{
class Program
{
static void Main(string[] args)
{
// created a a sample test time series of 10 days
DateTime Today = DateTime.Now;
var TimeSeries = new SortedList<DateTime, double>();
for (int i = 0; i < 10; i++)
TimeSeries.Add(Today.AddDays(i), i * 10);
// write out the time series
Console.WriteLine("Our time series contains...");
foreach (var item in TimeSeries)
Console.WriteLine(" {0}, {1}", item.Key.ToShortDateString(), item.Value);
// calculate an even period moving median
int period = 6;
var TimeSeries_MovingMedian = MovingMedian(TimeSeries, period);
// write out the result of the calculation
Console.WriteLine("\nThe moving median time series of {0} periods contains...", period);
foreach (var item in TimeSeries_MovingMedian)
Console.WriteLine(" {0}, {1}", item.Key.ToShortDateString(), item.Value);
// calculate an odd period moving median
int period2 = 5;
var TimeSeries_MovingMedian2 = MovingMedian(TimeSeries, period);
// write out the result of the calculation
Console.WriteLine("\nThe moving median time series of {0} periods contains...", period2);
foreach (var item in TimeSeries_MovingMedian2)
Console.WriteLine(" {0}, {1}", item.Key.ToShortDateString(), item.Value);
}
public static SortedList<DateTime, double> MovingMedian(SortedList<DateTime, double> TimeSeries, int period)
{
var result = new SortedList<DateTime, double>();
for (int i = 0; i < TimeSeries.Count(); i++)
{
if (i >= period - 1)
{
// add all of the values used in the calc to a list...
var values = new List<double>();
for (int x = i; x > i - period; x--)
values.Add(TimeSeries.Values[x]);
// ... and then sort the list <- there might be a better way than this
values.Sort();
// If there is an even number of values in the array (example 10 values), take the two mid values
// and average them. i.e. 10 values = (5th value + 6th value)/2.
double median;
if (period % 2 == 0) // is any even number
median = (values[(int)(period/2)] + values[(int)(period/2 - 1)])/2;
else // is an odd period
// Median equals the middle value of the sorted array, if there is an odd number of values in the array
median = values[(int)(period/2 + 0.5)];
result.Add(TimeSeries.Keys[i], median);
}
}
return result;
}
}
}
只有当您真的需要优化时才会进行优化。除此之外,我唯一看到的是你可以创建一个期望容量的循环外的值列表,但我不认为它会给你一个更好的速度。只是看起来更好。 – 2011-03-09 11:04:06