pyspark 笔记:窗口函数window

窗口函数相关的概念和基本规范可以见:pyspark笔记:over-CSDN博客

1 创建Pyspark dataFrame

from pyspark.sql.window import Window
import pyspark.sql.functions as F
employee_salary = [("Ali", "Sales", 8000),("Bob", "Sales", 7000),("Cindy", "Sales", 7500),("Davd", "Finance", 10000),("Elena", "Sales", 8000),("Fancy", "Finance", 12000),("George", "Finance", 11000),("Haffman", "Marketing", 7000),("Ilaja", "Marketing", 8000),("Joey", "Sales", 9000)]columns= ["name", "department", "salary"]
df = spark.createDataFrame(data = employee_salary, schema = columns)
df.show(truncate=False)

 

2 定义窗口规范

以 partitionBy 作为分组条件,orderBy 对 Window 分组内的数据进行排序

# 以 department 字段进行分组,以 salary 倒序排序
# 按照部门对薪水排名,薪水最低的为第一名
windowSpec = Window.partitionBy("department").orderBy(F.asc("salary"))

后面的示例如无特殊说明,都是使用这个窗口规范 

3 排名相关

3.1 row_number()

用于给出从1开始到每个窗口分区的结果的连续行号

df_part = df.withColumn("row_number", F.row_number().over(windowSpec)
)
df_part.show()

 

[观察上面的数据,发现同样的薪水会有不同的排名(比如Ali和Elena,都是8000的薪水,但一个第三一个第四),这是因为row_number()是按照行来给定序号,其不关注实际数值的大小。

3.1.1 应用举例:

找出每个department 薪水第二低的:

 df_part.where(F.col('row_number')==2).show()
'''
+------+----------+------+----------+
|  name|department|salary|row_number|
+------+----------+------+----------+
|George|   Finance| 11000|         2|
| Ilaja| Marketing|  8000|         2|
| Cindy|     Sales|  7500|         2|
+------+----------+------+----------+
'''

3.2 rank

不同于row_number,相同value的给相同值

df_part = df.withColumn('rank_number',F.rank().over(windowSpec))
df_part.show()
'''
+-------+----------+------+-----------+
|   name|department|salary|rank_number|
+-------+----------+------+-----------+
|   Davd|   Finance| 10000|          1|
| George|   Finance| 11000|          2|
|  Fancy|   Finance| 12000|          3|
|Haffman| Marketing|  7000|          1|
|  Ilaja| Marketing|  8000|          2|
|    Bob|     Sales|  7000|          1|
|  Cindy|     Sales|  7500|          2|
|    Ali|     Sales|  8000|          3|
|  Elena|     Sales|  8000|          3|
|   Joey|     Sales|  9000|          5|
+-------+----------+------+-----------+
'''

可以看到在rank下,Ali和Elena的rank_number是一样的了 

3.3 dense rank

先看结果,再看和rank的区别

df_part = df.withColumn('dense_rank_number',F.dense_rank().over(windowSpec))
df_part.show()
+-------+----------+------+-----------------+
|   name|department|salary|dense_rank_number|
+-------+----------+------+-----------------+
|   Davd|   Finance| 10000|                1|
| George|   Finance| 11000|                2|
|  Fancy|   Finance| 12000|                3|
|Haffman| Marketing|  7000|                1|
|  Ilaja| Marketing|  8000|                2|
|    Bob|     Sales|  7000|                1|
|  Cindy|     Sales|  7500|                2|
|    Ali|     Sales|  8000|                3|
|  Elena|     Sales|  8000|                3|
|   Joey|     Sales|  9000|                4|
+-------+----------+------+-----------------+

我们重点看Joey(最后一行),rank中Ali和Elena并列第三后,身后的Joey排名第五;dense_rank中,Joey紧跟着排第四 

3.4 percent_rank

百分位排名

df_part = df.withColumn('percent_rank_number',F.percent_rank().over(windowSpec))
df_part.show()
'''
+-------+----------+------+-------------------+
|   name|department|salary|percent_rank_number|
+-------+----------+------+-------------------+
|   Davd|   Finance| 10000|                0.0|
| George|   Finance| 11000|                0.5|
|  Fancy|   Finance| 12000|                1.0|
|Haffman| Marketing|  7000|                0.0|
|  Ilaja| Marketing|  8000|                1.0|
|    Bob|     Sales|  7000|                0.0|
|  Cindy|     Sales|  7500|               0.25|
|    Ali|     Sales|  8000|                0.5|
|  Elena|     Sales|  8000|                0.5|
|   Joey|     Sales|  9000|                1.0|
+-------+----------+------+-------------------+
'''

3.5 ntile

  •  ntile()可将分组的数据按照指定数值n切分为n个部分, 每一部分按照行的先后给定相同的序数。
  • 例如n指定为2,则将组内数据分为两个部分, 第一部分序号为1,第二部分序号为2。
  • 理论上两部分数据行数是均等的, 但当数据为奇数行时,中间的那一行归到前一部分。
df_part = df.withColumn('ntile(2)',F.ntile(2).over(windowSpec))
df_part.show()
'''
+-------+----------+------+--------+
|   name|department|salary|ntile(2)|
+-------+----------+------+--------+
|   Davd|   Finance| 10000|       1|
| George|   Finance| 11000|       1|
|  Fancy|   Finance| 12000|       2|
|Haffman| Marketing|  7000|       1|
|  Ilaja| Marketing|  8000|       2|
|    Bob|     Sales|  7000|       1|
|  Cindy|     Sales|  7500|       1|
|    Ali|     Sales|  8000|       1|
|  Elena|     Sales|  8000|       2|
|   Joey|     Sales|  9000|       2|
+-------+----------+------+--------+
'''

4  分析相关函数

4.1 cume_dist

数值的累进分布值

df.withColumn('cum_dist',F.cume_dist().over(windowSpec)).show()
'''
+-------+----------+------+------------------+
|   name|department|salary|          cum_dist|
+-------+----------+------+------------------+
|   Davd|   Finance| 10000|0.3333333333333333|
| George|   Finance| 11000|0.6666666666666666|
|  Fancy|   Finance| 12000|               1.0|
|Haffman| Marketing|  7000|               0.5|
|  Ilaja| Marketing|  8000|               1.0|
|    Bob|     Sales|  7000|               0.2|
|  Cindy|     Sales|  7500|               0.4|
|    Ali|     Sales|  8000|               0.8|
|  Elena|     Sales|  8000|               0.8|
|   Joey|     Sales|  9000|               1.0|
+-------+----------+------+------------------+
'''

这个表怎么解读呢?以Sales为例,薪资小于等于7000的占比0.2,薪资小于等于7500的占比0.4,以此类推

 4.2 lag

照指定列排好序的分组内每个数值的上一个数值

df.withColumn('lag',F.lag('name').over(windowSpec)).show()
'''
+-------+----------+------+-------+
|   name|department|salary|    lag|
+-------+----------+------+-------+
|   Davd|   Finance| 10000|   null|
| George|   Finance| 11000|   Davd|
|  Fancy|   Finance| 12000| George|
|Haffman| Marketing|  7000|   null|
|  Ilaja| Marketing|  8000|Haffman|
|    Bob|     Sales|  7000|   null|
|  Cindy|     Sales|  7500|    Bob|
|    Ali|     Sales|  8000|  Cindy|
|  Elena|     Sales|  8000|    Ali|
|   Joey|     Sales|  9000|  Elena|
+-------+----------+------+-------+
'''

4.3 lead

和lag相反,下一个值

df.withColumn('lead',F.lead('name').over(windowSpec)).show()
'''
+-------+----------+------+------+
|   name|department|salary|  lead|
+-------+----------+------+------+
|   Davd|   Finance| 10000|George|
| George|   Finance| 11000| Fancy|
|  Fancy|   Finance| 12000|  null|
|Haffman| Marketing|  7000| Ilaja|
|  Ilaja| Marketing|  8000|  null|
|    Bob|     Sales|  7000| Cindy|
|  Cindy|     Sales|  7500|   Ali|
|    Ali|     Sales|  8000| Elena|
|  Elena|     Sales|  8000|  Joey|
|   Joey|     Sales|  9000|  null|
+-------+----------+------+------+
'''

 5 聚合函数

此时的聚合样式为:

windowSpecAgg=Window.partitionBy('department')

5.1 avg

平均值

df.withColumn('avg',F.avg('salary').over(windowSpecAgg)).show()
'''
+-------+----------+------+-------+
|   name|department|salary|    avg|
+-------+----------+------+-------+
|   Davd|   Finance| 10000|11000.0|
|  Fancy|   Finance| 12000|11000.0|
| George|   Finance| 11000|11000.0|
|Haffman| Marketing|  7000| 7500.0|
|  Ilaja| Marketing|  8000| 7500.0|
|    Ali|     Sales|  8000| 7900.0|
|    Bob|     Sales|  7000| 7900.0|
|  Cindy|     Sales|  7500| 7900.0|
|  Elena|     Sales|  8000| 7900.0|
|   Joey|     Sales|  9000| 7900.0|
+-------+----------+------+-------+
'''

 5.2 sum 求和

5.3 min/max 最大最小值

5.4 count 这一个窗口内有多少记录

df.withColumn('count',F.count('salary').over(windowSpecAgg)).show()
'''
+-------+----------+------+-----+
|   name|department|salary|count|
+-------+----------+------+-----+
|   Davd|   Finance| 10000|    3|
|  Fancy|   Finance| 12000|    3|
| George|   Finance| 11000|    3|
|Haffman| Marketing|  7000|    2|
|  Ilaja| Marketing|  8000|    2|
|    Ali|     Sales|  8000|    5|
|    Bob|     Sales|  7000|    5|
|  Cindy|     Sales|  7500|    5|
|  Elena|     Sales|  8000|    5|
|   Joey|     Sales|  9000|    5|
+-------+----------+------+-----+
'''

 5.5 approx_count_distinct 相同的值只记录一次

df.withColumn('ap_count',F.approx_count_distinct('salary').over(windowSpecAgg)).show()
'''
+-------+----------+------+--------+
|   name|department|salary|ap_count|
+-------+----------+------+--------+
|   Davd|   Finance| 10000|       3|
|  Fancy|   Finance| 12000|       3|
| George|   Finance| 11000|       3|
|Haffman| Marketing|  7000|       2|
|  Ilaja| Marketing|  8000|       2|
|    Ali|     Sales|  8000|       4|
|    Bob|     Sales|  7000|       4|
|  Cindy|     Sales|  7500|       4|
|  Elena|     Sales|  8000|       4|
|   Joey|     Sales|  9000|       4|
+-------+----------+------+--------+
'''

参考内容:【PySpark】窗口函数Window - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/632747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

USACO介绍 报名流程 成绩查询方式详解(文末有备赛资料)

USACO美国计算机奥林匹克活动 2023-2024新赛季的时间线安排是怎么样的? 2023-2024USACO竞赛时间 一般来说,USACO竞赛时间在12月-3月期间,每月都有一场比赛每次3-5小时,并在规定时间内完成3-4道题。23-24年USACO竞赛时间安排如下&a…

uniapp h5 生成 ubuntu桌面程序 并运行方法

uniapp h5 生成 ubuntu桌面程序 并运行方法,在window环境下开发,发布到ubuntu桌面,并运行 1、安装Nodejs 安装包官方下载地址:https://www.nodejs.com.cn/ 安装完后cmd,如图,即安装成功 2、通过Nodejs安装 electron…

[flutter]GIF速度极快问题的两种解决方法

原因: 当GIF图没有设置播放间隔时间时,电脑上会默认间隔0.1s,而flutter默认0s。 解决方法一: 将图片改为webp格式。 解决方法二: 为图片设置帧频率,添加播放间隔。例如可以使用GIF依赖组件设置每秒运行…

【音视频】基于NGINX如何播放rtmp视频流

背景 现阶段直播越来越流行,直播技术发展也越来越快。Webrtc、rtmp、rtsp是比较火热的技术,而且应用也比较广泛。本文通过实践来展开介绍关于rtmp如何播放。 概要 本文重点介绍基于NGINX如何播放rtmp视频流 正文 1、构造rtsp视频流 可以参考上一篇…

Cacti 前台SQL注入漏洞复现(CVE-2023-39361)

0x01 产品简介 Cacti 是一套基于 PHP,MySQL,SNMP 及 RRDTool 开发的网络流量监测图形分析工具。 0x02 漏洞概述 该漏洞存在于graph_view.php文件中。默认情况下,访客用户无需身份验证即可访问graph_view.php,在启用情况下使用时会导致SQL注入漏洞。 攻击者可能利用此漏洞…

HCIP-7

IPV6: 为什么使用IPV6: V4地址数量不够V4使用NAT,破坏了端到端原则 IPV6的优点: 全球单播地址聚合性强(IANA组织进行合理的分配)多宿主----一个接口可以配置N个地址--且这些地址为同一级别自动配置---1)…

IPhone、IPad、安卓手机、平板以及鸿蒙系统使用惠普无线打印教程

演示机型:惠普M281fdw,测试可行机型:惠普M277,惠普M452、惠普M283 点击右上角图标。 点击WI-FI Direct 开,(如果WI-FI Direct关闭,请打开!) 记录打印机的wifi名称(SSID)和密码。 打开IPhone、I…

django后台进行加密手机号字段,加密存储,解密显示

需求: 1 :员工在填写用户的手机号时,直接填写,在django后台中输入 2:当员工在后台确认要存储到数据库时,后台将会把手机号进行加密存储,当数据库被黑之后,手机号字段为加密字符 3:员…

AD导出BOM表 导出PDF

1.Simple BOM: 这种模式下,最好在pcb界面,这样的导出的文件名字是工程名字,要是在原理图界面导出,会以原理图的名字命名表格。 直接在菜单栏 报告->Simple BOM 即可导出物料清单,默认导出 comment pattern qu…

253:vue+openlayers 加载HERE多种地图(v2软件版本)

第253个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中添加HERE地图,并且含多种的表现形式。包括地图类型,文字标记的设置、语言的选择、PPI的设定。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果图配置方式示例源…

2023年移远车载全面开花,智能座舱加速进击

作为汽车智能化的关键组件,车载模组正发挥着越来越重要的作用。 移远通信进入车载模组领域近十年,已形成了完善的车载产品队列,不但在5G/4G车载通信、智能座舱、C-V2X车路协同等领域打造了一枝独秀的产品线,也推出了车规级Wi-Fi/蓝…

LaWGPT安装和使用教程的复现版本【细节满满】

文章目录 前言一、下载和部署1.1 下载1.2 环境安装1.3 模型推理 总结 前言 LaWGPT 是一系列基于中文法律知识的开源大语言模型。该系列模型在通用中文基座模型(如 Chinese-LLaMA、ChatGLM等)的基础上扩充法律领域专有词表、大规模中文法律语料预训练&am…

【FastAPI】请求体

在 FastAPI 中,请求体(Request Body)是通过请求发送的数据,通常用于传递客户端提交的信息。FastAPI 使得处理请求体变得非常容易。 请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据 注:不能使用 …

2024年回炉计划之排序算法(一)

算法是计算机科学和信息技术中的重要领域,涉及到问题求解和数据处理的方法。要学习算法,你可能需要掌握以下一些基本知识: 基本数据结构: 了解和熟练使用各种数据结构,如数组、链表、栈、队列、树和图等。数据结构是算…

Java导出Excel并合并单元格

需求:需要在导出excel时合并指定的单元格 ruoyi excel 项目基于若伊框架二次开发,本着能用现成的就不自己写的原则,先是尝试了Excel注解中needMerge属性 /*** 是否需要纵向合并单元格,应对需求:含有list集合单元格)*/public boolean needMer…

4人遇难,北京突发火情 富维烟火识别防止悲剧再次发生

在北京一处居民区,一场突如其来的火灾夺走了四条宝贵的生命。火情迅速蔓延,烟雾弥漫,居民们猝不及防。这一悲剧再次提醒我们,火灾预防和早期识别的重要性不容忽视。 在这样的背景下,北京富维图像公司开发的FIS智能图像…

搭建自己的媒体矩阵-关于三微一端的媒体矩阵最简方案

引言 随着互联网的快速发展,媒体矩阵已成为品牌宣传的重要战略。通过搭建自己的媒体矩阵,企业、品牌和个人能够更有效地触达目标受众,传递信息、建立品牌形象,并与用户进行深度互动。本文将深入探讨如何制定一个有效的三微一端媒…

高光谱分类论文解读分享之Grid Network: 基于各向异性视角下特征提取的高光谱影像分类

IEEE GRSL 2023:Grid Network: 基于各向异性视角下特征提取的高光谱影像分类 题目 Grid Network: Feature Extraction in Anisotropic Perspective for Hyperspectral Image Classification 作者 Zhonghao Chen , Student Member, IEEE, Danfeng Hong , Senior …

【H3C】配置AAA认证和Telnet远程登陆,S5130 Series交换机

AAA配置步骤为: 1.开启telent远程登陆服务 2.创建用户,设置用户名、密码、用户的服务类型 3.配置终端登录的数量 4.配置vlan-if的ip地址,用来远程登陆 5.允许对应的vlan通过 1.开启telent远程登陆服务 sys …

【驱动】I2C驱动分析(四)-关键API解析

简介 在Linux内核源代码中的driver目录下包含一个i2c目录 i2c-core.c这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口。   i2c-dev.c实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过适配器访设备时的主设备号都为89,次设备号…