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. base64和Blob互相转换

      1.base64转blob(二进制数据) /** * 将以base64的图片url数据转换为Blob * @param urlData 用url方式表示的base64图片数据 */ functio ...

  2. Android 10 终于来了!增加了不少新特性

    前言 Android 10 正式发布了,根据官网的介绍,聚焦于隐私可控.手机自定义与使用效率,此版本主要带来了十大新特性:   image 智能回复 使用机器学习来预测你在回复信息时可能会说些什么,这 ...

  3. CountDownLatch源码

    public class CountDownLatchExample1 { public static void main(String[] args) throws Exception { Exec ...

  4. 原生Ajax的怎么用?

    <script> function createXMLHttpRequest() { var xmlhttp; try { //先直接创建XMLHttpRequest xmlhttp = ...

  5. [转帖]spring、springMvc、springBoot和springCloud的联系与区别

    spring.springMvc.springBoot和springCloud的联系与区别 -- :: 尘光掠影 阅读数 文章标签: springspringmvcspringbootspringCl ...

  6. C语言 宏定义的1<<0 与 直接定义1 有什么区别

    [1]示例程序 如下示例代码: #include <stdio.h> #define TEST1 1 << 0 #define TEST2 (1 << 0) #de ...

  7. js实现对上传图片的路径转成base64编码,并且对图片进行压缩,实现预览功能1

    参考 https://blog.csdn.net/qq_31965515/article/details/82975381 https://www.cnblogs.com/zhangdiIT/p/78 ...

  8. tkinter添加背景音乐

    一.问题利用tkinter来写一个游戏,添加一个背景音乐提高可玩性. 二.解决1.安装pygame首先是利用pygame的一个播放流:[pip install pygame]来完成pygame的安装. ...

  9. 【C#常用方法】3.将DataTable一次性插入数据库表中(使用SqlBulkCopy)

    将DataTable一次性插入数据库表中(使用SqlBulkCopy) 1.SqlBulkCopy简介 SqlBulkCopy类是ADO.NET中专门用于数据库批量插入数据的类,其批量插入的执行速度是 ...

  10. [個人紀錄] windows form , usercontrol design 模式不見

    windows form 跟 usercontrol 都變成cs檔 無法點擊進入設計模式 <Compile Include="Form1.cs"/> <Compi ...