C#百分等级算法

时间:2017-09-28 18:31:31

标签: c# math statistics

我正在尝试对在旧程序上完成的计算进行逆向工程,但却无法完成。我需要计算前27%,中间46%和最低27%的数量。

我有以下数据集,每个数据集中包含11个值,以及程序产生的百分比和属于这些百分位数的值的数量。

Upper 27%: 4, Middle 46%: 4, Lower 27%: 3
values: 8,9,10,11,11,11,11,12,12,12,13

Upper 27%: 5, Middle 46%: 4, Lower 27%: 2
values: 2,3,4,4,4,4,5,5,5,5,5

Upper 27%: 2, Middle 46%: 8, Lower 27%: 1
values: 2,4,4,4,4,4,4,4,4,5,5

Upper 27%: 2, Middle 46%: 6, Lower 27%: 3
values: 13,17,17,18,19,19,19,21,21,23,24

我找到了诸如(n * p)之类的公式,其中n是值的数量,p是百分位数,但它似乎不适用于所有这些数据集以得到相同的结果。我有点失落,没有发现任何产生结果的东西。

我测试了我在互联网上找到的代码,但没有人在不同的数据集上工作过。

我尝试过的代码示例:

    internal static double percentile(double[] sortedData, double p)
    {
        if (p >= 100.0d) return sortedData[sortedData.Length - 1];

        double position = (double)(sortedData.Length + 1) * p / 100.0;
        double leftNumber = 0.0d, rightNumber = 0.0d;

        double n = p / 100.0d * (sortedData.Length - 1) + 1.0d;

        if (position >= 1)
        {
            leftNumber = sortedData[(int)System.Math.Floor(n) - 1];
            rightNumber = sortedData[(int)System.Math.Floor(n)];
        }
        else
        {
            leftNumber = sortedData[0]; // first data
            rightNumber = sortedData[1]; // first data
        }

        if (leftNumber == rightNumber)
            return leftNumber;
        else
        {
            double part = n - System.Math.Floor(n);
            return leftNumber + part * (rightNumber - leftNumber);
        }
    } 

我正在尝试做什么的公式或名称?我是否在百分位排名的正确轨道上?

1 个答案:

答案 0 :(得分:4)

你正走在正确的道路上。这确实是百分等级公式。我最初的想法是将值设置在第27个百分点(,它看着你的代码,看起来你也开始沿着这个路径),并弄清楚有多少值大于或小于;但是你提供的价值并不能很好地支持这些数字。

因此,我采用的方法是计算每个数字的百分等级,如果它们与您上面的百分位相匹配,则将其计入计数。这似乎是他们采取的方法。

公式(check out this website for more info)

PR% = L + ( 0.5 x S ) / N Where, L = Number of below rank, S = Number of same rank, N = Total numbers.

代码:

var lower = 0;
var middle = 0;
var upper = 0;

// var values = new int[] { 8, 9, 10, 11, 11, 11, 11, 12, 12, 12, 13 };
// var values = new int[] { 2, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5 };
// var values = new int[] { 2, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5 };
var values = new int[] { 13, 17, 17, 18, 19, 19, 19, 21, 21, 23, 24 };

var n = values.Length;

foreach(var i in values)
{
    var pr = ((values.Count(v => v < i) + (.5 * values.Count(v => v == i))) / n);
    if (pr < .27)
        lower += 1;
    else if (pr > .73)
        upper += 1;
    else
        middle += 1;
}

Console.WriteLine("Upper: " + upper);
Console.WriteLine("Middle: " + middle);
Console.WriteLine("Lower: " + lower);