PySpark DataFrame 添加自增 ID

本文原始地址:https://sitoi.cn/posts/62634.html

在用 Spark 处理数据的时候,经常需要给全量数据增加一列自增 ID 序号,在存入数据库的时候,自增 ID 也常常是一个很关键的要素。

在 DataFrame 的 API 中没有实现这一功能,所以只能通过其他方式实现,或者转成 RDD 再用 RDD 的 zipWithIndex 算子实现。

下面呢就介绍三种实现方式。

创建 DataFrame 对象

from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()

df = spark.createDataFrame(
[
{"name": "Alice", "age": 18},
{"name": "Sitoi", "age": 22},
{"name": "Shitao", "age": 22},
{"name": "Tom", "age": 7},
{"name": "De", "age": 17},
{"name": "Apple", "age": 45}
]
)
df.show()

输出:

+---+------+
|age| name|
+---+------+
| 18| Alice|
| 22| Sitoi|
| 22|Shitao|
| 7| Tom|
| 17| De|
| 45| Apple|
+---+------+

方式一:monotonically_increasing_id()

使用自带函数 monotonically_increasing_id() 创建,由于 spark 会有分区,所以生成的 ID 保证单调增加且唯一,但不是连续的

优点:对于没有分区的文件,处理速度快。

缺点:由于 spark 的分区,会导致,ID 不是连续增加。

df = df.withColumn("id", monotonically_increasing_id())
df.show()

输出:

+---+------+-----------+
|age| name| id|
+---+------+-----------+
| 18| Alice| 8589934592|
| 22| Sitoi|17179869184|
| 22|Shitao|25769803776|
| 7| Tom|42949672960|
| 17| De|51539607552|
| 45| Apple|60129542144|
+---+------+-----------+

如果读取本地的单个 CSV 文件 或 JSON 文件,ID 会是连续增加且唯一的。

方法二:窗口函数

利用窗口函数:设置窗口函数的分区以及排序,因为是全局排序而不是分组排序,所有分区依据为空,排序规则没有特殊要求也可以随意填写

优点:保证 ID 连续增加且唯一

缺点:运行速度满,并且数据量过大会爆内存,需要排序,会改变原始数据顺序。

from pyspark.sql.functions import row_number

spec = Window.partitionBy().orderBy("age")
df = df.withColumn("id", row_number().over(spec))
df.show()

输出:

+---+------+---+
|age| name| id|
+---+------+---+
| 7| Tom| 1|
| 17| De| 2|
| 18| Alice| 3|
| 22| Sitoi| 4|
| 22|Shitao| 5|
| 45| Apple| 6|
+---+------+---+

方法三:RDD 的 zipWithIndex 算子

转成 RDD 再用 RDD 的 zipWithIndex 算子实现

优点:保证 ID 连续 增加且唯一。

缺点:运行速度慢。

from pyspark.sql import SparkSession
from pyspark.sql.functions import monotonically_increasing_id
from pyspark.sql.types import StructField, LongType spark = SparkSession.builder.getOrCreate() schema = df.schema.add(StructField("id", LongType()))
rdd = df.rdd.zipWithIndex() def flat(l):
for k in l:
if not isinstance(k, (list, tuple)):
yield k
else:
yield from flat(k) rdd = rdd.map(lambda x: list(flat(x)))
df = spark.createDataFrame(rdd, schema)
df.show()

输出:

+---+------+---+
|age| name| id|
+---+------+---+
| 18| Alice| 0|
| 22| Sitoi| 1|
| 22|Shitao| 2|
| 7| Tom| 3|
| 17| De| 4|
| 45| Apple| 5|
+---+------+---+

PySpark DataFrame 添加自增 ID的更多相关文章

  1. 如何在MySQl数据库中给已有的数据表添加自增ID?

    由于使用MySQL数据库还没有多久的缘故,在搭建后台往数据库导入数据的时候发现新增的表单是没有自增id的,因次就有了上面这个问题. 解决方法 1.给某一张表先增加一个字段,这里我们就以node_tab ...

  2. Entity Framework添加记录时获取自增ID值

    与Entity Framework相伴的日子痛并快乐着.今天和大家分享一下一个快乐,两个痛苦. 先说快乐的吧.Entity Framework在将数据插入数据库时,如果主键字段是自增标识列,会将该自增 ...

  3. [转] Entity Framework添加记录时获取自增ID值

    本文转自:http://blog.csdn.net/educast/article/details/8632806 与Entity Framework相伴的日子痛并快乐着.今天和大家分享一下一个快乐, ...

  4. 解决在mysql表中删除自增id数据后,再添加数据时,id不会自增1的问题

    https://blog.csdn.net/shaojunbo24/article/details/50036859 问题:mysql表中删除自增id数据后,再添加数据时,id不会紧接.比如:自增id ...

  5. MySQL自增ID 起始值 修改方法

    在mysql中很多朋友都认为字段为AUTO_INCREMENT类型自增ID值是无法修改,其实这样理解是错误的,下面介绍mysql自增ID的起始值修改与设置方法. 通常的设置自增字段的方法: 创建表格时 ...

  6. mysql 数据库自增id 的总结

    有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ...

  7. 高并发非自增ID如何设计?

    博友们一起来讨论下高并发非自增ID如何设计? 底层是很重要的,我最近设计底层,通用底层. 我想跟大家谈论下这个话题: 如何在高并发环境下设计出一套好用的非自增ID的添加操作的解决方案?更新的操作我随机 ...

  8. mysql 返回自增id

    String dateNow=  DateTime.Now.ToString("yyyyMMddhhmmss"+  new Random().Next(1, 99)); //随机数 ...

  9. mysql插入数据后返回自增ID的方法,last_insert_id(),selectkey

    mysql插入数据后返回自增ID的方法 mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得 ...

随机推荐

  1. ELK原理

    为什么要使用Elasticsearch?​ 因为在我们中的数据,会随着时间变的非常多,若采用以往的模糊查询,模糊查询前置通配符,如:"%aa%",会放弃索引,导致数据表查询将变成全 ...

  2. React 积累

    1. Fragment 标签 使用介绍:因React要求每个组件都需要一个大的外层包裹起来才可以,否则报错,如果你并不想组件外层由一个大大外层包裹,则可以使用Fragment 标签 代码示例: imp ...

  3. shell equal

    #!/bin/shzero=0 status=1 let status=0 if [[ $status -eq $zero ]];then echo "bu >= 3.6"e ...

  4. Vue.js之入门

    1.What is Vue.js? Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架,通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 2.引入 ...

  5. c++ rvo vs std::move

    c++ rvo vs std::move To summarize, RVO is a compiler optimization technique, while std::move is just ...

  6. ASP.NET Core使用Docker-Compose实现多容器应用部署

    一.需求背景 人生苦短,我用.NET Core!前面的<ASP.NET Core使用Docker进行容器化托管和部署>基础课程我们学习了如何使用Docker来部署搭建ASP.NET Cor ...

  7. nginx负载均衡+keepalived高可用

    nginx负载均衡+keepalived高可用 环境准备 192.168.88.111:nginx + keepalived   MASTER 192.168.88.112:nginx + keepa ...

  8. AQS4源码

    @SuppressWarnings("restriction") public abstract class AbstractQueuedSynchronizer1 extends ...

  9. python 计算列表内容出现次数

    """python 计算列表内容出现次数""" #方法一: l = ['a','a','b','c','d','b','b','b'] te ...

  10. DELPHI网页开发神器UNIGUI的安装与演示

    UNIGUI安装和演示 uniGUI v1.0.0.1397(带注册机).rar在delphi10.2安装 提示:安装包可以自行在网上搜索下载,或者联系我获取都可以 这里讲下怎样安装的方法: 1)执行 ...