PySpark实战(四)——活用PySpark( DataFrames 与 Spark SQL)_Jupyter notebook中运行

目录

DataFrame的建立

Spark SQL 基本用法

自定义函数

对数据的操作

写入文件 & 从文件读取

关联查询

Spark读取JSON数据

Spark对日期数据进行处理

将DataFrame对象存入csv文件并读取


【私信发ipynb文件】

DataFrame的建立

类似传统数据库的二维表,包括自身数据和数据结构信息(Schema)

在Spark中,DataFrame支持嵌套数据类型,如array和map

DataFrame可以从多种数据来源上进行构建,如结构化数据文件、Hive中的表、外部数据库或现有RDD

import findspark
findspark.init()

from pyspark.sql import SparkSession

# 构建Spark对象
# 采用local模式,只使用一个CPU进行处理
# 使用getOrCreate()共享SparkContext。如果尚不存在,则创建SparkContext;如果已存在,则创建SparkContext的实例。
# getOrCreate使用参考链接:https://www.codenong.com/47813646/
spark = SparkSession.builder \
    .master("local[1]") \
    .appName("RDD Demo") \
    .getOrCreate();

sc = spark.sparkContext
a = [('Jack',32), ('Smith',33)]

df = spark.createDataFrame(a)
df.collect()
df.show()
df2 = spark.createDataFrame(a, ['name', 'age'])
df2.collect()
df2.show()

使用ROW创建

rdd = sc.parallelize(a)
print(rdd.collect())

from pyspark.sql import Row

# 创建一个包含列名的Row
Person = Row('name', 'age')

# 将RDD对象进行元素映射,转换成一个Person对象,并返回一个新的RDD对象,格式为[Row(name='Jack', age=32), Row(name='Smith', age=33)]
person = rdd.map(lambda r: Person(*r))
print(person.collect())

df = spark.createDataFrame(person)
df.collect()

创建具有字段类型的

from pyspark.sql.types import *

schema = StructType([
    # True代表是否可以为空
    StructField('name', StringType(), True),
    StructField('age', StringType(), True)
])

df = spark.createDataFrame(rdd, schema)
print(df.collect())

# print('\n')
print(df.show())

# print('\n')
# 打印df对象的Schema结构定义
print(df.printSchema())

更简单的方法

df = spark.createDataFrame(rdd, 'name:string, age:int')
df.collect()
df.printSchema()

#  提取第一个元素作为新的RDD
rdd2 = rdd.map(lambda row:row[0])
df2 = spark.createDataFrame(rdd2, 'string')
df2.collect()
df2.show()
df2.printSchema()

Spark SQL 基本用法

a = [('Jack',32), ('Smith',33), ('李四',35)]
rdd = sc.parallelize(a)

df = spark.createDataFrame(rdd, 'name:string, age:int')
df.count()
# 创建一个名为user的表,存入df的数据
df.createOrReplaceTempView('user')

df2 = spark.sql('select count(*) as counter from user')
df2.show()

自定义函数

conf = sc.getConf().get('spark.sql.shuffle.partitions')
print(conf)
# 利用该方法注册一个自定义用户函数strLen,其逻辑是返回参数的长度
strlen = spark.udf.register('strLen', lambda x:len(x))
df2 = spark.sql('select *, strLen(name) as len from user')
df2.show()

对数据的操作

df2 = df.select('name').where(strlen('name')>2)
df2.show()
# df.agg({key,value})
# key指字段
# value指执行的逻辑

df2 = df.agg({'age':'max'})
df2.show()
# 进行统计描述

df.describe(['age']).show()

写入文件 & 从文件读取

# 写入文件
df.write.parquet('myuser.parquet')

# 从文件导入
peopleDF = spark.read.parquet('myuser.parquet')
peopleDF.show()

进入jupyter目录下可以看见有一个文件夹,里面有四个文件

peopleDF.filter(peopleDF.age>32).show()

关联查询

# 创建第一个表
a = [
    ('01', '张三', '男', 32,5000),
    ('01', '李四', '男', 33,6000),
    ('01', '王五', '女', 38,5500),
    ('02', 'Jack', '男', 42,7000),
    ('02', 'Smith', '女', 27,6500),
    ('02', 'Lily', '女', 45,9500),
]
rdd = sc.parallelize(a)
peopleDf = spark.createDataFrame(rdd, 'deptId:string, name:string, gender:string, age:int, salary:int')
peopleDf.show()

# 创建第二个表
b = [
    ('01', '销售部'),
    ('02', '研发部')
]
rdd2 = sc.parallelize(b)
deptDf = spark.createDataFrame(rdd2, 'id:string, name:string')
deptDf.show()

method默认为inner,

也可选

cross, uter, full, full_outer, left, left_outer, right, right_outer, left_semi, left_anti

# 进行连接
# df1.join(df2, action, method)
# action是条件,method是连接方式

peopleDf.join(deptDf, peopleDf.deptId == deptDf.id, 'inner') \
        .groupBy(deptDf.name, 'gender') \
        .agg({'salary':'avg', 'age':'max'}) \
        .show()

 【若需要去重,只需要在show()之前调用    .distinct()     即可  】

【若要删去某一列,在show()之前调用   .drop('列名1', '列名2')  】

从行上移除数据

【从一个DataFrame中移除另一个DataFrame的数据】

df1 = spark.createDataFrame([('a',1), ('a',1), ('a',1), ('a',2), ('b',3), ('c',4)], ['c1', 'c2'])
df2 = spark.createDataFrame([('b', 3), ('a',1)], ['c1', 'c2'])

df1.exceptAll(df2).show()

# 从df1中删除df2
# 若有重复数据,只排除一个

 【求交集】

print(df1.show())
print(df2.show())

df1.intersectAll(df2).sort('c1','c2').show()

 【空值处理】

a = [
    ('01', '张三', '男', 32,5000),
    ('01', '李四', '男', 33,6000),
    ('01', '王五', '女', 38,5500),
    ('02', 'Jack', '男', 42,7000),
    ('02', 'Smith', '女', 27,6500),
    ('02', 'Lily', '女', 45,None),
]
rdd = sc.parallelize(a)
peopleDf = spark.createDataFrame(rdd, 'deptId:string, name:string, gender:string, age:int, salary:int')
peopleDf.show()
peopleDf.na.fill({'salary':0, 'name':'unknown'}).show()

None值显示为null,.na.fill()进行替换

 【综合操作示例】

a = [
    ('01', '张三', '男', 32,5000),
    ('01', '李四', '男', 33,6000),
    ('01', '王五', '女', 38,5500),
    ('02', 'Jack', '男', 42,7000),
    ('02', 'Smith', '女', 27,6500),
    ('02', 'Lily', '女', 45,9500),
]
rdd = sc.parallelize(a)
peopleDf = spark.createDataFrame(rdd, 'deptId:string, name:string, gender:string, age:int, salary:int')


# 转成JSON格式
print(peopleDf.toJSON().collect())

# 给出对象的概览统计结果
peopleDf.summary().show()

# 添加age2列
peopleDf.withColumn('age2', peopleDf.age+1) \
        .withColumnRenamed('name', '姓名') \
        .show()

# 选择表达式
peopleDf.selectExpr('age+1', 'salary*1.2').show()

Spark读取JSON数据

去jupyter目录下新建 user.json文件,添加下面的内容

{"deptId":"01","name":"张三","gender":"男","age":32,"salary":5000},
{"deptId":"01","name":"李四","gender":"男","age":33,"salary":6000},
{"deptId":"01","name":"王五","gender":"女","age":38,"salary":5500},
{"deptId":"02","name":"Jack","gender":"男","age":42,"salary":7000},
{"deptId":"02","name":"Smith","gender":"女","age":27,"salary":6500},
{"deptId":"02","name":"Lily","gender":"女","age":45,"salary":9500}

# JSON数据不能有[]

# 从user.json目录下读取文件,并转换成DataFrame对象
df = spark.read.format('json').load('user.json')
df.show()

# 打印字段类型
df.dtypes

# 透视
# 按照deptId分组,将genedr字段的值转置到列,形成透视表,汇总字段为salary的和

df2 = df.groupBy('deptId').pivot('gender').sum('salary')
df2.show()

# 条件选择
# df.salary.between(6000,9500)是一个字段表达式,而不是类似where子句的过滤

df.select('name', df.salary.between(6000,9500)).show()

# 选择name和age两列,筛选条件是 df.name.like(‘Smi%’)

df.select('name', 'age').where(df.name.like('Smi%')).show()

Spark对日期数据进行处理

df = spark.createDataFrame([('2020-05-10',), ('2020-05-09',)], ['dt'])

from pyspark.sql.functions import add_months


# add_months(df.dt, 1) 对dt字段进行+1处理,计算下个月日期
# alias('next_month') 对字段进行重命名

df.select(add_months(df.dt, 1).alias('next_month')).show()

将DataFrame对象存入csv文件并读取

# 从user.json目录下读取文件,并转换成DataFrame对象
df = spark.read.format('json').load('user.json')
df.show()
# 写入csv文件(其实对应一个目录,不是传统csv文件)
# 写入模式有两种   append追加模式;overwrite覆盖模式
# 给定的是数据存储的路径,而非存储的文件名

df.write.csv('user.csv', 'append')


# 读取csv文件

spark.read.csv('user.csv').show()

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值