pyspark 笔记:窗口函数window

news2024/9/30 11:25:40

窗口函数相关的概念和基本规范可以见: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.coloradmin.cn/o/1395789.html

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

相关文章

UI自动化Selenium 无头模式运行

1、导入浏览器参数设置 from selenium.webdriver.chrome.options import Options 2、创建参数,并使用无厘头模式创建driver对象 opt Options() # 新建参数对象 opt.add_argument("--headless") # 无头 self.driver webdriver.Chrome(optionsopt) …

【数据结构】哈希表详解,举例说明 java中的 HashMap、HashTable及其区别

一、哈希表(Hash Table)简介: 哈希表是一种数据结构,用于实现字典或映射等抽象数据类型。它通过把关键字映射到表中的一个位置来实现快速的数据检索。哈希表的基本思想是利用哈希函数将关键字映射到数组的索引位置上,…

四款免费、易用的Docker漏洞扫描工具

本文向您介绍四种既可以扫描Docker镜像中的漏洞,又能够被轻松地集成到CI/CD中的四种免费实用工具。 基本原理 所有这些工具的工作原理都比较类似。它们使用的是如下两步流程: 生成软件物料清单(Software Bill of Materials,SBOM)。将SBOM与…

USB PHY for FPGA layout

https://blog.csdn.net/qq_41904778/article/details/123967670 ZYNQ7000内部没有USB PYH,我们通过USB 3320 PHY 芯片来连接FPGA 和外部的USB端口(DP & DP-)。USB 3320 PHY跟FPGA内部是t通过ULPI接口试下的,然后把数据转化为…

windows下编译报‘mutex‘ in namespace ‘std‘ does not name a type的解决方案

问题复述: windows下使用MinGW编译工程时,报如下错误: error: ‘mutex’ in namespace ‘std’ does not name a type error: ‘mutex’ is not a member of ‘std’ error: ‘mutex’ was not declared in this scope 问题分析&#xff…

C#,字符串匹配(模式搜索)Sunday算法的源代码

Sunday算法是Daniel M.Sunday于1990年提出的一种字符串模式匹配算法。 核心思想:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配&…

跨域原理和解决方案

前置知识 什么是跨域 主要是由于浏览器的同源策略引起的,同源策略是浏览器的安全机制,当 协议,域名,端口 三者有一个不同,浏览器就禁止访问资源。 比如:http://www.company.com:80 http://www.company.…

chatgpt的实用技巧四temperature 格式

四、temperature 格式 GPT3.5 temperature 的范围为:0-0.7; GPT4.0 temperature 的范围为:0-1; 当 temperature 为 0 时候,结果可稳定。 当 temperature 为 0.7/1 时候,结果发散具备创力。 数值越大&a…

【动态规划】24子数组系列_最长湍流子数组_C++

题目链接:最长湍流子数组 目录 题目解析: 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目解析: 题目让我们求返回 arr 的 最大湍流子数组的长度 由题可得: 如果比较符号在子数组中的…

使用 ClassFinal 对SpringBoot jar加密加固并进行机器绑定

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!如果我的博客对你有帮助,欢迎进行评论✏️✏️、点赞👍👍、收藏⭐️⭐️&#…

告别繁琐配置!JVS低代码逻辑引擎让你轻松实现高效数据处理

在当今高度数字化的世界中,逻辑引擎作为数据处理和业务逻辑的核心组件,其重要性不言而喻。它不仅关乎企业数据的准确处理,还影响着业务决策的效率和准确性。为了确保逻辑引擎的正常运行和准确性,配置和测试环节显得尤为重要。 本…

【技术】MySQL数据读写分离怎么实现

、概念: MySQL数据读写分离是存储数据的一种服务架构执行select命令必须连接 slave角色服务器执行insert命令必须连接 maste角色服务器提供数据读写分离功能的中间件软件有: mysql-proxy maxscale mycat拓扑架构只支持一主一从或者一主多从架构 二、实…

Docker搭建MySQL主从数据库-亲测有效

1、测试环境概述 1、使用MySQL5.7.35版本 2、使用Centos7操作系统 3、使用Docker20版本 案例中描述了整个测试的详细过程 2、安装Docker 2.1、如果已经安装docker,可以先卸载 yum remove -y docker \ docker-client \ docker-client-latest \ docker-common \ docker-l…

Spring-BeanPostProcessor PostConstruct init InitializingBean 执行顺序

执行顺序探究 新建一个对象用于测试 Component public class Student implements InitializingBean {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}pu…

Red Hat Enterprise Linux 7.9 安装图解

引导和开始安装 选择倒计时结束前,通过键盘上下键选择下图框选项,启动图形化安装过程。 安装语言选择 这里要区分一下,当前选中的语言作为安装过程中安装器所使用的语言,这里我们选择中文简体。不过细心的同学可能发现&#xff0c…

Js-WebAPIs-事件流(三)

• 事件流与两个阶段说明 事件流指的是事件完整执行过程中的流动路径 说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父 实际工作都是…

Debian系统写Mysql时中文出现乱码无法定入的问题解决方案

原因是操作系统可能精简安装,没有GBK字符集,只有UTF8在转换或使用的时候有问题。 使用locale -a查看系统支持的字符集。正常的比较全的字符集的操作系统如下: 有问题的操作系统字符集如下: 解决方案: 步骤1&#…

LiveNVR监控流媒体Onvif/RTSP功能-服务接收RTSP推流RTSPServer可以拉转配置到通道中视频直播

LiveNVR服务接收RTSP推流RTSPServer可以拉转配置到通道中视频直播 1、需求背景2、开启RTSP2.1、基础配置配置RTSP端口 3、获取RTSP推流地址3.1、RTSP推流地址格式3.3、RTSP推流地址示例 4、配置设备推流5、配置拉转RTSP5.1、直播流地址格式5.2、直播流地地址示例5.3、通道配置直…

滑雪挑战H5小游戏

欢迎来到程序小院 滑雪挑战 玩法&#xff1a;点击鼠标左键控制人物滑雪的方向&#xff0c;注意不同的弯道&#xff0c;滑雪过程中会有⭐️&#xff0c;看你会获得⭐️&#xff0c;快去滑雪吧^^。开始游戏https://www.ormcc.com/play/gameStart/254 html <canvas id"c…

文件系统和IO流

目录 ​文件系统和IO流 一:文件的认知 认识文件 树型结构组织和⽬录: 文件路径&#xff08;Path): 文件形式: 二:File的方法 File的概述: File的属性 File的构造方法 File常用的get系列方法 ⽰例一:观察get系列的特点和差异 File常用的增,删方法 示例二:普通文件…