2015-02-13 3 views
1

У меня есть некоторые результаты, которые хранятся в многомерном массиве:Сalculate некоторые статистические данные с Math.Net

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]. К сожалению, нет другого (более ясного) сообщения об ошибке.

Можете ли вы помочь мне понять, где проблема, и есть ли лучший способ рассчитать процентиль по столбцу?

ответ

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)); 

, который кажется намного яснее.

+0

Ничего себе это работает красиво. Но я получаю некоторые NaN в результатах. Это может быть из-за некоторых NaN в временных рядах. Как я могу изменить запрос, чтобы избежать этого NaN? Спасибо. – mickG

+0

@mickG - Фильтр с 'double.IsNan()'. – dbc

+0

Благодарим вас за помощь. Все это работает так, как ожидалось. – mickG

Смежные вопросы