Расчет процентиля

Я хочу имитировать функцию PERCENTILE, эквивалентную Excel, в C# (или в каком-то псевдокоде). Как я могу это сделать? Функция должна принимать два аргумента, где первый - это список значений, а второй - для какого процентиля функция должна рассчитывать.

Танки!

Изменить: извините, если мой вопрос возник так, как будто я сам не пробовал. Я просто не мог понять, как работает функция excel (да, я сначала попробовал википедию и вольфрам), и я подумал, что пойму это лучше, если кто-то представит это в коде. @CodeInChaos дал ответ, который кажется мне тем, что мне нужно.


person picknick    schedule 15.11.2011    source источник
comment
не могли бы вы привести пример псевдокода использования функции, входных данных и ожидаемого результата вывода?   -  person sll    schedule 15.11.2011
comment
Что вы пробовали?   -  person Justin    schedule 15.11.2011


Ответы (3)


Я думаю, что на странице Википедии есть формулы, необходимые для написания собственной функции ...
Я пробовал это:

public double Percentile(double[] sequence, double excelPercentile)
{
    Array.Sort(sequence);
    int N = sequence.Length;
    double n = (N - 1) * excelPercentile + 1;
    // Another method: double n = (N + 1) * excelPercentile;
    if (n == 1d) return sequence[0];
    else if (n == N) return sequence[N - 1];
    else
    {
         int k = (int)n;
         double d = n - k;
         return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);
    }
}

ИЗМЕНЕНО после комментария CodeInChaos:
Excel использует значение процентиля от 0 до 1 (поэтому я изменил свой код, чтобы реализовать это с помощью формул Википедии) и другой метод для вычисления n (поэтому я изменил прокомментированный один).

person Marco    schedule 15.11.2011
comment
@picknick: Я только что написал соответствующую функцию со страницы Википедии. Это должен быть тот, который используется (согласно Википедии) в Excel. - person Marco; 15.11.2011
comment
Две проблемы: 1) Excel, похоже, использует метод (N-1) 2) Он представляет процентиль числом от 0 до 1. - person CodesInChaos; 15.11.2011
comment
@CodeInChaos: спасибо за ваш комментарий. Я не знаю, как работает Excel, я только что перевел формулы Википедии на C #, предполагая, что часть, относящаяся к Excel, была правильной. Что вы думаете? Это не так? Я думаю, OP нуждался в способе вычисления процентиля, даже потому, что существует множество методов. В любом случае ваша точка зрения важна для меня. Дай мне кое-что знать. Спасибо! :) - person Marco; 15.11.2011
comment
@CodeInChaos: я изменил свой код, чтобы отразить то, что вы предложили, после проверки того, что делает Excel. Большое спасибо :) - person Marco; 15.11.2011
comment
Вы неправильно читаете Википедию. Формула (N+1) уже является частью следующего раздела, в котором говорится о процентах NIST. Я предполагаю, что часть /100, вероятно, предназначена для согласованности с остальной частью страницы. Также, похоже, используется часть +1, потому что массивы Excel индексируются 1, тогда как C # использует массивы на основе 0. - person CodesInChaos; 15.11.2011
comment
@CodeInChaos: Я пробовал свой код с формулами Википедии и Excel, и оба соответствуют ... В Википедии используется процентиль P от 1 до 100, поэтому, я думаю, для этого подходит / 100. Я ошибся? ;) - person Marco; 15.11.2011
comment
Ваш код округляет параметр percentile до ближайшего значения, кратного 0,01. Не уверен, что Excel делает такие вещи, но считаю такое поведение удивительным. (По той же причине мне не нравится TimeSpan.FromSeconds) - person CodesInChaos; 15.11.2011
comment
@CodeInChaos: вы правы, я проверил Excel и этого округления не происходит. Снова отредактировал ... и еще раз спасибо !! :) - person Marco; 15.11.2011
comment
Это вызывает исключение ArgumentOutOfRangeException в последней строке блока else (return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);) - person Edward Karak; 07.11.2013
comment
@EdwardKarak: покажите нам свою последовательность и процентиль, переданные в функцию, чтобы мы могли попытаться помочь ... - person Marco; 07.11.2013
comment
Я решил проблему. Я неправильно прочитал утверждение, что Excel использует значение процентиля от 0 до 1, и я вводил числа больше 1. - person Edward Karak; 08.11.2013
comment
компилятор выдает предупреждение из-за == сравнения двойников. Чтобы обойти эту проблему, я предлагаю заменить n == 1 на n ‹= 1, idem для n == N следующим образом: if (n‹ = 1) return sequence [0]; иначе, если (n ›= N) вернуть последовательность [N - 1]; - person shelbypereira; 10.12.2016

Попытка воспроизвести результаты по адресу: http://www.techonthenet.com/excel/formulas/percentile.php Я придумал:

public static double Percentile(IEnumerable<double> seq,double percentile)
{
    var elements=seq.ToArray();
    Array.Sort(elements);
    double realIndex=percentile*(elements.Length-1);
    int index=(int)realIndex;
    double frac=realIndex-index;
    if(index+1<elements.Length)
        return elements[index]*(1-frac)+elements[index+1]*frac;
    else
        return elements[index];
}

(Не обрабатывает NaN и бесконечности).

Несколько тестовых примеров:

Percentile(new double[]{1,2,3,4}, 0.8).Dump();// 3.4
Percentile(new double[]{7,8,9,20}, 0.35).Dump();// 8.05
Percentile(new double[]{1,2,3,4}, 0.3).Dump();// 1.9
person CodesInChaos    schedule 15.11.2011

Добавьте значения в список, отсортируйте этот список и возьмите значение индекса ceil (длина списка * процентиль).

person stracktracer    schedule 15.11.2011
comment
Это не соответствует функции процентиля Excel. Кажется, используется линейная интерполяция между ближайшими значениями. - person CodesInChaos; 15.11.2011