1

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

double[,] results;

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

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

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

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

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

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

4

1 回答 1

2

Percentile是一种扩展方法调用顺序如下:

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

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

但是,results.GetLength(2)会抛出异常,因为 的维度参数GetLength()是从零开始的。你可能的意思是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));

这似乎更清楚。

于 2015-02-14T00:13:36.360 回答