hive分位函数percentile和percentile

2024-07-06 1445阅读

hive分位函数percentile和percentile_approx误区和解决方案

先说结论

percentile和percentile_approx对分位数的计算是不同的!!!

hive分位函数percentile和percentile
(图片来源网络,侵删)

拿中位数来说,

percentile(col, 0.5),结果和正常理解的中位数相同,即col排序后最中间的一个数(col观察数为奇数时)或者最中间两个数的平均数(col观察数为偶数时)为中位数;

percentile_approx(col, 0.5),则是按照等频划分的方法来计算中位数的。

分位函数用法

介绍分位函数的用法

  1. 整数类型 percentile

percentile(col, p):col是要计算的列(值必须为整数类型);参数p取值为0-1。

当需要多个分位数的时候,可以用array数组,格式为:percentile(col, array(p1, p2, …,pn))

  1. 浮点或整数类型 percentile_approx

percentile_approx(col, p, B):col是要计算的列(值可以是浮点类型);参数p取值为0-1;参数B控制内存消耗的近似精度,B越大,结果的精度越高,默认值为10000,当col字段中的distinct值的个数小于B时,结果就为准确的百分位数,可不填。

当需要多个分位数的时候,可以用array数组,格式为:percentile_approx(col, array(p1, p2, …,pn), B)

分位函数用法示例

建表语句:col_int 为整数,col_double 为浮点数

CREATE TABLE  test.test_table
(
	`col_int` int
	,`col_double` double
) 

插入数据:9条(奇数条)

insert into test.test_table values 
	(1, 0.15)
	,(2, 0.25)
	,(3, 0.35)
	,(4, 0.45)
	,(5, 0.55)
	,(6, 0.65)
	,(7, 0.75)
	,(8, 0.85)
	,(9, 0.95)

查询结果:中位数,即50分位数

-- 查询1
select percentile(t.col_int, 0.5) from test.test_table t ; -- 5
-- 查询2
select percentile_approx(t.col_int, 0.5) from test.test_table t ; -- 4.5
-- 查询3
select percentile_approx(t.col_double, 0.5) from test.test_table t ; -- 0.5

疑问

为什么整数列 col_int 使用 percentile 和 percentile_approx 的结果不一样?

为什么浮点数列 col_double 使用 percentile_approx 的结果是0.5而不是0.55?

解析

对于整数列的中位数:

percentile 在奇数个数值时,排序后,第(n+1)/2位数 即为中位数,所以查询1的结果是5;

percentile 在偶数个数值时,排序后,第n/2位数 和 第n/2+1位数 的平均值即为中位数;

percentile_approx 通过等频率划分来计算中位数,在奇数个数值时,排序后,第1个数的为累积概率1/9,依次第4个数的累积概率为4/9,第5个数的累积概率为5/9,等频率中位数的计算为 (4 x (1/2 - 4/9) + 5 x (5/9 - 1/2) / (5/9 - 4/9) = 4.5 ,化简可以得到 (4+5)/2,即 第(n+1)/2位数 和 第(n-1)/2位数 的平均值为等频中位数;

percentile_approx 在偶数个数值时,排序后,第n/2位数 的累积概率为0.5,故 第n/2位数 即为等频中位数。

对于浮点数列的中位数:

percentile_approx 计算等频中位数的方法同上。

验证

往表里新增一条数据,把数据集变成偶数列,验证上述解析:

insert into test.test_table values 
	(10, 1.05)

查询结果:符合预期

-- 查询4
select percentile(t.col_int, 0.5) from test.test_table t ; -- 5.5
-- 查询5
select percentile_approx(t.col_int, 0.5) from test.test_table t ; -- 5
-- 查询6
select percentile_approx(t.col_double, 0.5) from test.test_table t ; -- 0.55

提问:如果想对浮点数取中位数而不是等频中位数怎么办?

可以对浮点数列乘以相应的倍数,转化为整数列,使用percentile获得想要的中位数。例如:

-- 查询7
select percentile(int(t.col_double * 100), 0.5) / 100 from test.test_table t ; -- 0.6
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]