使用Math.Net计算一些统计数据

时间:2015-02-13 23:40:01

标签: c# arrays list multidimensional-array mathnet

我有一些存储在多维数组中的结果:

double[,] results;

每列是特定变量(例如“房屋”,“汽车”,“电力”)的价格的时间序列。我想计算每个变量的一些统计数据,以便以更紧凑的形式总结结果。 例如,我正在研究Math.Net中的百分位函数。

我想计算每列价格的第90个百分位数(因此对于每个变量)。

我正在尝试以下方法,因为该函数不适用于多维数组(因此我无法将结果[,]作为百分位函数的参数传递):

for (int i = 0, i <= results.GetLength(2), i++)
{
    myList.Add(MathNet.Numerics.Statistics.Statistics.Percentile(results[,i], 90));
}

所以我想遍历我的结果列[,]并计算第90个百分位,将结果添加到列表中。 但这不起作用,因为结果[,i]中的语法错误。遗憾的是,没有其他(更明确的)错误消息。

您能帮助我了解问题所在,以及是否有更好的方法按列计算百分位数?

1 个答案:

答案 0 :(得分:2)

Percentile是一个extension method,其中包含以下calling sequence

public static double Percentile(this IEnumerable<double> data, int p)

因此,您可以使用Linq将您的2d数组转换为适当的序列以传递给Percentile

但是,results.GetLength(2)会抛出异常,因为dimension argument of GetLength() is zero-based。您可能意味着results.GetLength(1)。假设这就是你的意思,你可以这样做:

        var query = Enumerable.Range(0, results.GetLength(1))
            .Select(iCol => Enumerable.Range(0, results.GetLength(0))
                .Select(iRow => results[iRow, iCol])
                .Percentile(90));

您可以让Linq为您列出清单,

        var myList= query.ToList();

或将其添加到预先存在的列表中:

        myList.AddRange(query);

<强>更新

要过滤NaN值,请使用double.IsNaN

        var query = Enumerable.Range(0, results.GetLength(1))
            .Select(iCol => Enumerable.Range(0, results.GetLength(0))
                .Select(iRow => results[iRow, iCol])
                .Where(d => !double.IsNaN(d))
                .Percentile(90));

<强>更新

如果有人提取了几个数组扩展名:

public static class ArrayExtensions
{
    public static IEnumerable<IEnumerable<T>> Columns<T>(this T[,] array)
    {
        if (array == null)
            throw new ArgumentNullException();
        return Enumerable.Range(0, array.GetLength(1))
            .Select(iCol => Enumerable.Range(0, array.GetLength(0))
                .Select(iRow => array[iRow, iCol]));
    }

    public static IEnumerable<IEnumerable<T>> Rows<T>(this T[,] array)
    {
        if (array == null)
            throw new ArgumentNullException();
        return Enumerable.Range(0, array.GetLength(0))
            .Select(iRow => Enumerable.Range(0, array.GetLength(1))
                .Select(iCol => array[iRow, iCol]));
    }
}

查询变为:

        var query = results.Columns().Select(col => col.Where(d => !double.IsNaN(d)).Percentile(90));

这似乎更清楚。