图表中百分位数的计算

概要

在做图表的时候,经常会需要计算一组数据的百分位数是多少的问题。下面总结了两种计算百分位数的方法和区别,最后附上工具函数

例如:

计算出下面这组数据中的75百分位数:“[23.66, 4.52, 23.98, 9.34, 5.44]”

方法一

比较简单的一种方法,准确度欠佳,计算出的数值是原始数据中的某一个数字或者某两个相邻数字的平均数

	const arr = [23.66, 4.52, 23.98, 9.34, 5.44];
	//第一步,对数组进行排序(从小到大)
	arr.sort((a,b)=>a-b)//arr 变为 [ 4.52, 5.44, 9.34, 23.66, 23.98 ]
	// 第二步,计算指数i 0.75表示75百分位
	const i = arr.length*0.75//3.75
	//第三步,计算百分位数, 这里根据i的值会有两种处理方式。
	//当i是整数时,取arr中第i-1和第i位数字的平均数;
	//当i不是整数时,将i向上取整,然后取取整后的数字。 
	//当前例子中i=3.75,所以用第二种情况的计算方式
	const result = arr[Math.ceil(i)-1]//23.66

方法二

较为准确的计算方法,是基于SPSS和SAS所使用的。它涉及到计算指数(n+1)P%=j+g,其中j为整数部分,g为小数部分。X表示排序后的数组,P百分位数=g*X(j+1)+(1-g)X(j)=X(j)+g[X(j+1)-X(j)],从公式可以得出,当g=0时,P百分位数=X(j)

	const arr = [23.66, 4.52, 23.98, 9.34, 5.44];
	//第一步,对数组进行排序(从小到大)
	arr.sort((a,b)=>a-b)//arr 变为 [ 4.52, 5.44, 9.34, 23.66, 23.98 ]
	// 第二步,计算指数i 0.75表示75百分位
	const i = (arr.length+1)*0.75//4.5
	// 第三步,判断i是否是整数,如果不是需要进一步计算出  j(整数部分) 和 g(小数部分)
	let j,g;
	if(Number.isInteger(i)){
		j = i-1;
		g = 0;
	}else{
		[j,g] = i.toString().split(".")
		j=Number(j)
		g=Number("0."+g)
	}
	//第四步,根据计算公式计算百分位数 P百分位数=X(j)+g[X(j+1)-X(j)],
	//注意:X[j]=arr[j-1],数组下标是从0开始的,所以第j个数是arr[j-1]
	const result = arr[j-1]+g*(arr[j]-arr[j-1])//23.82

小结

从上述两个结果来看,第一种方案更为简单一些,第二种更为精确一些。具体要使用哪种方法计算,是需要根据实际需求来的,最后再附上一个转换函数;觉得对你有用的话,记得点赞收藏+关注

/***
     * 计算一组数据中的指定百分位数
     * target:Array 源数据
     * percentitle:0~1的数字  百分位
     * type: 1|2 1表示简单算法   2表示精确算法
     * */
    function arr2px(target, percentile, type = 2) {
        if (!Array.isArray(target) && target.length > 1) {
            console.log('传入target参数和符合要求')
            return
        }
        if (!(percentile > 0 && percentile < 1)) {
            console.log('传入percentile参数和符合要求')
            return
        }
        if (type !== 1 && type !== 2) {
            console.log('传入type参数和符合要求')
            return
        }
        const sortArr = target.toSorted((a, b) => a - b)
        const n = sortArr.length
        if (type === 1) {
            const i = n * percentile;
            if (Number.isInteger(i)) {
                return (sortArr[i - 1] + sortArr[i]) / 5
            } else {
                return sortArr[Math.ceil(i) - 1]
            }
        } else {
            debugger
            const i = (n + 1) * percentile
            let j, g;
            if (Number.isInteger(i)) {
                j = i, g = 0
            } else {
                [j, g] = (i + "").split(".");
                j = +j, g = +("0." + g)
            }
            return sortArr[j - 1] + g * (sortArr[j] - sortArr[j - 1])
        }
    }

    // test
    const arr = [23.66, 4.52, 23.98, 9.34, 5.44];
    const p1 = arr2px(arr, 0.75, 1)//23.66
    const p2 = arr2px(arr, 0.75)//23.82
    console.log(p1, p2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全村最肉的人

如果对你有用,就赏博主1分钱!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值