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

Calculate some statistics with Math.Net

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

double[,] results;

每一列都是特定变量的价格时间序列(例如 "house"、"car"、"electricity")。我想为每个变量计算一些统计数据,以便以更紧凑的形式总结结果。 例如,我正在查看 Math.Net 中的百分位数函数。

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

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

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

所以我想遍历结果的列[] 并计算第 90 个百分位数,将结果添加到列表中。 但这行不通,因为 results[ i] 中的语法错误。不幸的是,没有其他(更清楚的)错误消息。

你能帮我了解问题出在哪里吗?是否有更好的方法来按列计算百分位数?

Percentile is an extension method with following calling sequence:

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

因此您可以使用 Linq 将二维数组转换为适当的序列以传递给 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));

看起来更清楚了。