Spark类SQL要点总结

本文详细介绍了Spark中的RDD和DataFrame的区别,包括DataFrame的创建方式(如toDF、createDataFrame和从文件读取),以及DataFrame的SQL操作、数据清洗、聚合、连接、分组和窗口函数的使用。
摘要由CSDN通过智能技术生成

总 结

问:Spark中RDD和sparkDataFrame的区别

1 SparkDF创建与保存

1.1 toDF

将RDD转化为DataFrame

df = rdd.toDF(schema=['name', 'age'])
1.2 通过createDataFrame方法
1.2.1 将Pandas的DataFrame转换为pyspark的DataFrame
df = spark.createDataFrame(pd_df)
1.2.2 将python的list转换为pyspark的DataFrame
df = spark.createDataFrame(
    data=data,
    schema=['name', 'age'])

1.2.3指定rdd和schema创建DataFrame

schema = 'name string, age int, birth date'
df = spark.createDataFrame(data=rdd, schema=schema)
1.3 通过读取文件创建DataFrame
df = spark.read.json('data/iris.json')
df = spark.read.csv('data/iris.csv', sep=',', inferSchema=True, header=True)
df = spark.read.csv('data/iris.txt', sep=',', inferSchema=True, header=True)
df = spark.read.parquet('data/iris.parquet')
df = spark.sql('select * from edu.course')

1.4 SparkDF保存

df.write.csv('data/iris_csv', header=True)
df.rdd.saveAsTextFile('data/iris_txt')
df.rdd.saveAsTextFile('data/iris_txt')
df.write.json('data/iris_json')
df.write.parquet('data/iris_parquet')
# 分区, 分文件夹存储
df.write.partitionBy('label').format('parquet').save('data/iris_parquet_par')
spark.sql('create database db')

2 SparkDF类SQL

2.1 读取数据
  • 预览前1行: df.first()

  • 预览前3行: df.head(3)

  • 预览后3行: df.tail(3)

  • 预览所有行: df.collect()

  • 预览表数据:df.show(5)

  • 查看字段名称\数据类型\是否可空等, 元数据:df.printSchema()

  • 查看字段列表:df.columns

  • 查看字段数据类型:df.dtypes

  • 查看行数:df.count()

  • 查看文件路径:df.inputFiles()

2.2 类SQL基本操作(清洗)
2.2.1 读取列
# 读取所有字段
# df.select('*').show()
# df.show()
​
# 读取指定字段
# df.select('order_id', 'region', 'province', 'quantity').show(5)
# df[['order_id', 'region', 'province', 'quantity']].show(5)
# df['order_id', 'region', 'province', 'quantity'].show(5)
# df.select(df.order_id, df.region, df.province, df.quantity).show(5)
df.select(df['order_id'], df['region'], df['province'], df['quantity']).show(5)
# 正则表达式读取指定字段, 必须加``
df.select(df.colRegex('`order.*`')).show(5)
2.2.2 新增列
# 金额=价格*数量
df = df.withColumn('amount', df['price'] * df['quantity'])
2.2.3 删除列
df.drop('region', 'product_type').show(1)
2.2.4 重命名列
(df.withColumnRenamed('order_id', '订单编号')
    .withColumnRenamed('order_date', '订单日期')
    .withColumnRenamed('product_type', '产品类型')
    .show(1))
2.2.5 排序
# sort或orderBy
df.sort(df['order_date'].desc()).show(1)
# 多列排序
df.orderBy(df['region'].asc(), df['order_date'].desc()).show(1)
2.2.6 替换
# 将"办公用品"和"家具产品"都替换为"办公和家具"
lst = ['办公用品', '家具产品']
df.replace(to_replace=lst, value='办公和家具', subset='product_type').show(5)
2.2.7 删除空值
# df.na.drop或dropna
# 如两列均为空, 则删除整行, all and 与/且
df.dropna(how='all', subset=['region', 'province']).show(1)
​
# 如两列其中一列为空, 则删除整行, any or 或
df.dropna(how='any', subset=['region', 'province']).show(1)
2.2.8 填充空值
df.fillna(value=0, subset='profit').show(1)
2.2.9 删除重复值
# drop_duplicates或dropDuplicates
# 根据所有字段来删除重复行
df.dropDuplicates().show(1)
​
# 根据指定字段来删除重复行
df.drop_duplicates(subset=['order_id', 'region']).show(1)
2.2.10 转换字段数据类型
df.select(
    df['price'].astype(t.IntegerType()),
    df['quantity'].astype(t.FloatType())
).show(5)
2.2.11 转换DataFrame格式
  • 将spark的df转换为pandas的df

pd_df = df.toPandas()
  • 将spark的df转换为json

    df.toJSON().take(1)
  • 将spark的df转换为python迭代器

it = df.toLocalIterator()
# 迭代器可以记住遍历的位置, 只能向前访问不能后退, 直到所有元素访问完毕为止
for row in it:
    print(row)
    time.sleep(3)
2.3 Spark类SQL的统计操作
2.3.1 整表聚合计算
df.agg({'price': 'max', 'quantity': 'sum'}).show()
2.3.2 描述统计
# describe
df.select('price', 'quantity', 'profit').describe().show()
​
# summary
df.select('price', 'quantity', 'profit').summary().show()
2.3.2 频数统计
df.freqItems(cols=['province', 'quantity'], support=0.6).show()
2.3.3 分位数
# col, 统计字段
# probabilities概率/百分位, 0-1, 必须为浮点数, 求多个分位数时传递列表或元组,
# relativeError相对误差, 浮点数, 0.0表示精确计算
# 该函数返回列表
# df.stat.approxQuantile
lst = df.approxQuantile('price', [0.0, 0.5, 1.0], 0.0)
type(lst)

2.4 Spark类Sql的表操作
2.4.1 表查询
  • distinct去重

df.distinct().count()
  • limit限制行数

df.select('order_id', 'order_date').limit(2).show()
  • where筛选

df.where("product_type='办公用品' and quantity > 10").show(3)
  • filter筛选,# where等价于filter

    # df.filter("product_type='办公用品' and quantity > 10").show(3)
    # df.filter((df['product_type'] == '办公用品') & (df['quantity'] > 10)).show(3)
    ​
    # df.where("region in ('华南', '华北') and price > 100").show(3)
    # df.where((df['region'].isin(['华南', '华北'])) & (df['price'] > 100)).show(3)
    ​
    # like通配符筛选, %表示任意数量任意字符, _任意单个字符
    # df.where("province like '湖%'").show(3)
    # df.where(df['province'].like('湖%')).show(3)
    ​
    # rlike正则表达式筛选
    # df.where("province rlike '湖北|湖南'").show(3)
    # df.where(df['province'].rlike('湖北|湖南')).show(3)
    ​
    # 广播变量筛选, 性能更好
    bc = sc.broadcast(['华南', '华北'])
    df.where(df['region'].isin(bc.value)).show(5)
    # df.where(~df['region'].isin(bc.value)).show(5)
  • 条件判断

    # when和otherwise类似于SQL的case when
    from pyspark.sql import functions as f
    df.select(
        'order_id', 'profit',
        f.when(df['profit'] > 0, '盈利')
        .when(df['profit'] == 0, '持平').otherwise('亏损').alias('state')
    ).show(3)
2.4.2 表连接
  • inner内连接

    people.join(salary, on='id', how='inner').show()
  • left左连接

    people.join(salary, on='id', how='left').show()
  • right右连接

    people.join(salary, on='id', how='right').show()
2.4.3 分组聚合
  • groupBy,以区域分组,对数量求和

df.groupBy('region').agg(f.sum('quantity').alias('quantity')).show()
  • groupBy+agg,以区域分组,统计单价的均值,合并产品类型

# collect_list不去重, collect_set去重
# mean等价于avg
from pyspark.sql import functions as f
df.groupBy('region').agg(
    f.avg('price').alias('price_avg'),
    f.collect_set('product_type').name('product_set')
).show()
​
# 上面的等价写法
df.groupBy('region').agg(
    f.expr('avg(price)').alias('price_avg'),
    f.expr('collect_set(product_type)').alias('product_set')
).show()
​
df.groupBy('region').agg(
    f.expr('avg(price) as price_avg'),
    f.expr('collect_set(product_type) as product_set')
).show()
  • groupBy+pivot,数据透视表,行:区域,列:产品类型,值:数量,计算类型:求和

df.groupBy('region').pivot('product_type').sum('quantity').show()

2.4.4 窗口函数 window

window = Window.partitionBy('product_type').orderBy(df['order_date'].asc()) \
    .rowsBetween(Window.unboundedPreceding, Window.currentRow)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值