我有一些存储在多维数组中的结果:
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]中的语法错误。遗憾的是,没有其他(更明确的)错误消息。
您能帮助我了解问题所在,以及是否有更好的方法按列计算百分位数?
答案 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));
这似乎更清楚。