Hive学习小记-(14)如何写SQL求出中位数平均数和众数(count 之外的方法)

摘要:
均值、中值和模式是衡量一组数据集趋势的统计数据。中位数为1200人,其中5人处于同等水平,占大多数。不受极值影响,当一组数据中的某些数据重复出现时,模式通常是最受关注的数量。更好地获取所需信息。
平均数中位数众数

平均数、中位数、众数都是度量一组数据集中趋势的统计量。所谓集中趋势是指一组数据向某一中心值靠拢的倾向,测度集中趋势就是寻找数据一般水平的代表值或中心值。而这三个特征数又各有特点,能够从不同的角度提供信息。

平均数


  • 特点:计算用到所有的数据,它能够充分利用数据提供的信息,它具有优秀的数学性质,因此在实际应用中较为广泛。但它受极端值的影响较大。
  • 应用场合:没有极端值的情况下数据集中趋势的刻画。
  • 如:小明五次测试的成绩为87、88、89、93、94你认为小明这五次测试成绩怎样?
  • 分析:

中位数


  • 特点:中位数是一组数据中间位置的代表值。计算简单,不受极端值的影响,但不能充分利用每个数据所提供的信息。
  • 应用场合:有极端值,且无某数据重复出现多次的情况下集中趋势的刻画。
  • 如:某公司员工月工资如下:
    这个公司员工的月工资有一般水平是多少?
    • 员工         经理 副经理 员工a  员工b  员工c   员工d   员工e   员工f    杂工
    • 月工资/元 6000 4000   1700  1300   1200    1100    1100    1100     500
  • 分析:这组数据的平均数是2000,而高于这一水平的只有2人,不具有代表性。其中位数是1200,处于其相当水平的有5人,占大多数。较好的反映了一般水平。

众数


    • 特点:众数是一组数据中出现次数最多的数据。不受极端值的影响,当一组数据中某些数据多次重复出现时,众数往往是人们最关心的一个量。但它不能象平均数那样充分利用数据提供信息。
    • 应用场合:有极端值,有某些数据多次重复出现时。
    • 如:一家鞋店在一段时间内销售了某种女鞋30双,各种尺码鞋的销量如下:
      你能为这家鞋店提供进货建议吗?
      • 尺码/厘米   22   22.5   23    23.5    24    24.5    25
      • 销售量/双    1     1        2       5      15      5        1
    • 分析:由于进货最关心的是哪种尺码的鞋最多,而这里很明显24码的要占相当大的量15双。较好的得到所需信息。
需求描述

一道SQL题:如何SQL求出中位数平均数和众数(count 之外的方法)

创建样例数据
import pyspark
from pyspark.sql import SparkSession

sc=SparkSession.builder.master("local")
    .appName('first_name1')
    .config('spark.executor.memory','2g')
    .config('spark.driver.memory','2g')
    .enableHiveSupport()
    .getOrCreate()

sc.sql(''' drop  table test_youhua.test_avg_medium_freq ''')
sc.sql(''' CREATE TABLE if not exists test_youhua.test_avg_medium_freq(name string,income int) ''')
sc.sql(''' INSERT into test_youhua.test_avg_medium_freq VALUES ('桑普森', '400000'),('迈克', '30000'),('怀特', '20000'),('阿诺德', '20000')
,('史密斯', '20000'),('劳伦斯', '15000'),('哈德逊', '15000'),('肯特', '10000'),('贝克', '10000'),('斯科特', '10000') ''')
sc.sql(''' select * from test_youhua.test_avg_medium_freq ''').show()
+----+------+
|name|income|
+----+------+
| 桑普森|400000|
|  迈克| 30000|
|  怀特| 20000|
| 阿诺德| 20000|
| 史密斯| 20000|
| 劳伦斯| 15000|
| 哈德逊| 15000|
|  肯特| 10000|
|  贝克| 10000|
| 斯科特| 10000|
+----+------+

求均值(人均薪资):

#1.avg() 因为存在一个员工,多条薪资记录的情况,所以需要先分组统计
sc.sql(''' SELECT AVG(a.income) FROM (
           SELECT SUM(income) AS income FROM test_youhua.test_avg_medium_freq
           GROUP BY name
           ) AS a ''').show()
# 2.sum/人数
sc.sql(''' SELECT SUM(income)/COUNT(DISTINCT name) AS avg_income
FROM test_youhua.test_avg_medium_freq ''').show()
+-----------+
|avg(income)|
+-----------+
|    55000.0|
+-----------+

求中位数

1.用笛卡尔积,然后判断哪条元素位于中间位置,取中间位置元素均值

#1、问题显示如下所示:
#Use the CROSS JOIN syntax to allow cartesian products between these relation
#2、原因:
#Spark 2.x版本中默认不支持笛卡尔积操作
#3、解决方案:
#通过参数spark.sql.crossJoin.enabled开启,方式如下:
sc.conf.set("spark.sql.crossJoin.enabled", "true")
sc.sql(""" select avg(tmp.income) from (  --如果是奇数直接取,若是偶数取平均
--先做笛卡尔积,计算每条数据对应的上半部分(大于该条)、下半部分(小于该条)两个子集,求其交集(即中间位置元素),这时若聚合数据的数目是奇数,最后得一条,偶数得两条)
             select t1.income    
             from test_youhua.test_avg_medium_freq t1,test_youhua.test_avg_medium_freq t2
             group by t1.income
             having sum(case when t1.income>=t2.income then 1 else 0 end)>=count(*)/2
                and sum(case when t2.income>=t1.income then 1 else 0 end)>=count(*)/2
           ) as tmp
           """).show()
+-----------+
|avg(income)|
+-----------+
|    17500.0|
+-----------+

2.用percentage函数

参考:https://www.jianshu.com/p/57129421ee85

参考:https://blog.csdn.net/qq_33637730/article/details/109066665

在hive环境中,可以使用percentile(BIGINT col, p)来查找中位数,但该函数中的列只能使用整型,我们也可以使用percentile_approx()来近似中位数

percentile_approx还有一种形式percentile_approx(col, p,B),参数B控制内存消耗的近似精度,B越大,结果的精度越高。默认值为10000。当col字段中的distinct值的个数小于B时,结果就为准确的百分位数  

sc.sql(""" select percentile(income,0.5) from test_youhua.test_avg_medium_freq""").show()
+---------------------------------------+
|percentile(income, CAST(0.5 AS DOUBLE))|
+---------------------------------------+
|                                17500.0|
+---------------------------------------+

3.用row_number

sc.sql(""" select avg(income) from ( 
             select income,
             row_number() over( order by income ) num,
             count(*) over( ) cnt
             from test_youhua.test_avg_medium_freq 
            ) as tmp
            --如果是奇数,取排序中间的,如果是偶数,取两个中间的均值
         where if(cnt%2=0,num in(cnt/2,cnt/2+1),num=(cnt+1)/2)""").show() #数据量非常大时,这里或许可以直接使用num=ceil(cnt/2)
+-----------+
|avg(income)|
+-----------+
|    17500.0|
+-----------+

求众数

参考:https://www.cnblogs.com/tgzhu/p/9946628.html

 1.用having +count(max)

#HIve没有all,any的用法,只能用max来定位出现次数最多的了
#https://issues.apache.org/jira/browse/HIVE-15229
#1. 'LIKE ANY' operator return true if a text(column value) matches to any pattern.
#2. 'LIKE ALL' operator return true if a text(column value) matches to all patterns.
#3. 'LIKE ANY' and 'LIKE ALL' returns NULL not only if the expression on the left hand side is NULL, but also if one of the pattern in the list is NULL.
#sc.sql("""SELECT income from test_youhua.test_avg_medium_freq 
#          group by income
#          where count(*)>=all(select count(*) from test_youhua.test_avg_medium_freq group by income) """).show()
sc.sql("""SELECT income from test_youhua.test_avg_medium_freq 
          group by income
          having count(*)>=(select max(num) from (select count(*) as num from test_youhua.test_avg_medium_freq group by income)) """).show()
+------+
|income|
+------+
| 10000|
| 20000|
+------+

 

免责声明:文章转载自《Hive学习小记-(14)如何写SQL求出中位数平均数和众数(count 之外的方法)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu13.04使用Mesapython+selenium一:对浏览器的操作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

大数据平台Hive数据迁移至阿里云ODPS平台流程与问题记录

一、背景介绍 最近几天,接到公司的一个将当前大数据平台数据全部迁移到阿里云ODPS平台上的任务。而申请的这个ODPS平台是属于政务内网的,因考虑到安全问题当前的大数据平台与阿里云ODPS的网络是不通的,所以不能使用数据采集工作流模板。 然而,考虑到原大数据平台数据量并不是很大,可以通过将原大数据平台数据导出到CSV文件,然后再将CSV文件导入到ODPS平...

Hive 元数据库表信息

  Hive 的元数据信息通常存储在关系型数据库中,常用MySQL数据库作为元数据库管理。 1. 版本表   i) VERSION   -- 查询版本信息 2. 数据库、文件存储相关   i) DBS     -- 存储Hive中所有数据库的基本信息   ii) SDS    -- 存储Hive中文件存储的基本信息      3. 表、视图相关   i) ...

Windows环境下安装Hadoop+Hive的使用案例

 正文前先来一波福利推荐: 福利一: 百万年薪架构师视频,该视频可以学到很多东西,是本人花钱买的VIP课程,学习消化了一年,为了支持一下女朋友公众号也方便大家学习,共享给大家。 福利二: 毕业答辩以及工作上各种答辩,平时积累了不少精品PPT,现在共享给大家,大大小小加起来有几千套,总有适合你的一款,很多是网上是下载不到。 获取方式: 微信关注 精品3分钟...

Hive中文注释乱码解决方案(2)

本文来自网易云社区 作者:王潘安 执行阶段 launchTask    回到Driver类的runInternal方法,看以下执行过程。在runInternal方法中,执行过程调用了execute方法。execute方法里面的内容很多,但是跟我们有关系的就只有launchTask方法。这个方法里面有这么关键的几步:      tsk.initializ...

Java连接Hive使用Zookeeper的方式

  Java连接Hive的方式就是通过JDBC的方式来连接,URL为jdbc:hive2://host:port/db;principal=X@BIGDATA.COM等,这种方式是直接连接HiveServer2服务的,但是在现实中,还有一种以Zookeeper的方式去连接,例如: jdbc:hive2://zk01:2181,zk02:2181,zk03:...

Spark python集成

Spark python集成 1、介绍 Spark支持python语言,对于大量的SQL类型的操作,不需要编译,可以直接提交python文件给spark来运行,因此非常简单方便,但是性能要比scala或java慢。对于常规任务,可以使用python来编写,特殊任务还是建议scala编写。 2、使用pyspark启动spark shell(centos) 2...