使用 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));
看起来更清楚了。
我有一些结果存储在多维数组中:
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));
看起来更清楚了。