pyspark 笔记:窗口函数window

这篇具有很好参考价值的文章主要介绍了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)

pyspark 笔记:窗口函数window,python库整理,笔记 

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()

pyspark 笔记:窗口函数window,python库整理,笔记 

[观察上面的数据,发现同样的薪水会有不同的排名(比如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 - 知乎文章来源地址https://www.toymoban.com/news/detail-803841.html

到了这里,关于pyspark 笔记:窗口函数window的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Python】PySpark 数据计算 ① ( RDD#map 方法 | RDD#map 语法 | 传入普通函数 | 传入 lambda 匿名函数 | 链式调用 )

    在 PySpark 中 RDD 对象 提供了一种 数据计算方法 RDD#map 方法 ; 该 RDD#map 函数 可以对 RDD 数据中的每个元素应用一个函数 , 该 被应用的函数 , 可以将每个元素转换为另一种类型 , 也可以针对 RDD 数据的 原始元素进行 指定操作 ; 计算完毕后 , 会返回一个新的 RDD 对象 ; map 方法 , 又

    2024年02月14日
    浏览(55)
  • Windows中处理PySpark报错:SparkException: Python worker failed to connect back

    Windows中处理PySpark报错:SparkException: Python worker failed to connect back 这个问题可能是发送在windows10以上的版本,使用datafram的方法是没问题,但是使用rdd算子出现这个问题,报错SparkException: Python worker failed to connect back。环境变量的设置一下PYSPARK_PYTHON 改成自己的python环境 就可以

    2024年01月16日
    浏览(50)
  • 选读SQL经典实例笔记15_窗口函数

    2.2.1.1. 分组不为空 2.2.1.1.1. 一个分组至少要拥有一个成员(行 2.2.1.1.2. 无法从一个空表中生成任何分组 2.2.1.2. 分组具有唯一性 2.2.1.2.1. 如果查询语句使用了GROUP BY子句,那么通常而言SELECT列表里就不再需要使用DISTINCT了 2.2.2.1. COUNT永远大于0 2.2.2.1.1. 无法从一个空表

    2024年02月14日
    浏览(41)
  • EasyUI Jquery 学习笔记 —— Window(窗口)详细版

    通过 $.messager.defaults 重写默认的 defaults。 消息框(messager)提供不同样式的消息框,包括警示(alert)、确认(confirm)、提示(prompt)、进展(progress)等等。所有的消息框都是异步的。用户可以在与消息框交互后使用回调函数来完成一些动作。 依赖 window linkbutton progressbar

    2024年04月15日
    浏览(41)
  • 【Python】PySpark 数据计算 ③ ( RDD#reduceByKey 函数概念 | RDD#reduceByKey 方法工作流程 | RDD#reduceByKey 语法 | 代码示例 )

    RDD#reduceByKey 方法 是 PySpark 中 提供的计算方法 , 首先 , 对 键值对 KV 类型 RDD 对象 数据 中 相同 键 key 对应的 值 value 进行分组 , 然后 , 按照 开发者 提供的 算子 ( 逻辑 / 函数 ) 进行 聚合操作 ; 上面提到的 键值对 KV 型 的数据 , 指的是 二元元组 , 也就是 RDD 对象中存储的数据是

    2024年02月14日
    浏览(54)
  • 学习笔记整理-面向对象-02-认识函数的上下文

    什么是上下文 函数的上下文 函数中可以使用 this ,它表示 函数的上下文 。 与中文中\\\"这\\\"类似,函数中的this具体指代什么 必须通过调用函数时的\\\"前言后语\\\"来判断 函数中的this 函数的上下文由调用方式决定 同一个函数,用不同的形式调用它,则函数的上下文不同 情形

    2024年02月13日
    浏览(37)
  • Flutter笔记:桌面应用 窗口定制库 bitsdojo_window

    Flutter笔记 桌面应用窗口管理库 bitsdojo_window 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/134464678 高级:多窗口管理,请跳转到:《Flutter桌面端应用多窗口管理》,地址:https://jclee95.blog.csdn.net

    2024年02月01日
    浏览(40)
  • Python - 操作windows程序窗口

    ● 在自动化测试脚本中,有时候需要自动安装windows程序,或者操作windows程序。对于操作windows程序的python库五花八门,本文以pyautoit库演示如何操作windows程序窗口。 ● pyautoit库是AutoIt v3工具的python接口,直接绑定到AutoItX3.dll。AutoIt v3工具可以实现通过模拟鼠标、键盘对win

    2024年02月05日
    浏览(38)
  • python --根据windows窗口名称、进程pid打开窗口(pygetwindow详解)

    简介: pygetwindow 是一个Python库,用于获取、操作和管理当前打开的窗口。它提供了一些常用的窗口操作方法,包括获取窗口句柄,获取窗口位置和大小,移动和调整窗口大小,最小化、最大化和还原窗口,以及模拟输入和焦点控制等。 安装 详解 获取当前所有窗口 获取指定标

    2024年02月07日
    浏览(81)
  • Python获取与设置Windows当前窗口

    在Python做屏幕自动化的过程中,难免需要涉及对窗口的操作,理论上都可以用鼠标键盘+屏幕识别(对人的完全模拟)来实现,但具体做起来实在有点麻烦。如果不考虑跨平台的兼容性,那么引入win32gui库,可以省很多事。 获取当前窗口 查找窗口 设置当前窗口

    2023年04月08日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包