Spark(三)-- SparkSQL扩展(数据操作) -- 转换操作(一)

目录

8. Dataset (DataFrame) 的基础操作

8.1 有类型操作

8.1.1 转换类型的操作

8.1.2 过滤类型的操作

8.1.3 集合类型的操作

8.1.4 切分类型的操作

8.1.5 排序类型的操作

8.1.6 分区类型的操作

8.1.7 去重类型的操作

8.1.8 集合类型的操作

8.2 无类型操作

8.2.1 选择类型的操作

8.2.2 剪切类型的操作

8.2.3 聚合类型的操作


8. Dataset (DataFrame) 的基础操作

导读

这一章节主要目的是介绍 Dataset 的基础操作, 当然, DataFrame 就是 Dataset, 所以这些操作大部分也适用于 DataFrame

  1. 有类型的转换操作

  2. 无类型的转换操作

  3. 基础 Action

  4. 空值如何处理

  5. 统计操作

8.1 有类型操作

8.1.1 转换类型的操作

转换类型的操作主要包含:flatMap、map、mapPartitions、transform、as

(1)flatMap

方法描述:通过 flatMap 可以将一条数据转为一个数组, 后再展开这个数组放入 Dataset

    val ds = Seq("hello spark","hello hadoop").toDS
    ds.flatMap( x => x.split(" ")).show()

(2)map

方法描述:map 可以将数据集中每条数据转为另一种形式(通过传入计算函数来实现)

    val ds2 = Seq(Person("张三",18),Person("李四",20)).toDS()
    ds2.map( person => Person(person.name,person.age*2)).show()

(3)mapPartitions

方法描述:mapPartitions 和 map 一样, 但是 map 的处理单位是每条数据, mapPartitions 的处理单位是每个分区

    ds2.mapPartitions(
      //iter 不能大到每个Executor的内存放不下,不然就会OOM
      //对每个元素进行转换,后生成一个新的集合
      iter => {
        val result = iter.map(person => Person(person.name,person.age*2))
        result
      }
    ).show()

(4)transform

方法描述:map 和 mapPartitions 以及 transform 都是转换, map 和 mapPartitions 是针对数据, 而 transform 是针对整个数据集, 这种方式最大的区别就是 transform 可以直接拿到 Dataset 进行操作

    val ds = spark.range(10)
    //对数据集的操作
    ds.transform(dataset => dataset.withColumn("doubled",'id*2))
      .show()

(5)as

方法描述:as[Type] 算子的主要作用是将弱类型的 Dataset 转为强类型的 Dataset, 它有很多适用场景, 但是最常见的还是在读取数据的时候, 因为 DataFrameReader 体系大部分情况下是将读出来的数据转换为 DataFrame 的形式, 如果后续需要使用 Dataset 的强类型 API, 则需要将 DataFrame 转为 Dataset. 可以使用 as[Type] 算子完成这种操作

  @Test
  def as(): Unit = {
    // 1. 读取
    val schema = StructType(
      Seq(
        StructField("name", StringType),
        StructField("age", IntegerType),
        StructField("gpa", FloatType)
      )
    )

    val df: DataFrame = spark.read
      .schema(schema)
      .option("delimiter", "\t")
      .csv("dataset/studenttab10k")

    // 2. 转换
    // 本质上: Dataset[Row].as[Student] => Dataset[Student]
    // Dataset[(String, int, float)].as[Student] => Dataset[Student]
    val ds: Dataset[Student] = df.as[Student]

    // 3. 输出
    ds.show()
  }

8.1.2 过滤类型的操作

过滤类型的操作主要包含:filter

(1)filter

方法描述:用来按照条件过滤数据集

    val ds = Seq(Person("张三",15),Person("李四",20)).toDS()
    ds.filter( person => person.age>15 ).show()

8.1.3 集合类型的操作

集合类型的操作主要包含:groupBykey

(1)groupByKey

方法描述:grouByKey 算子的返回结果是 KeyValueGroupedDataset, 而不是一个 Dataset, 所以必须要先经过 KeyValueGroupedDataset 中的方法进行聚合, 再转回 Dataset, 才能使用 Action 得出结果。
其实这也印证了分组后必须聚合的道理

  @Test
  def groupByKey():Unit={
    val ds = Seq(Person("张三",15),Person("张三",15),Person("李四",20)).toDS()
    //select count(*) from person group by name
    val grouped: KeyValueGroupedDataset[String, Person] = ds.groupByKey(person => person.name)
    val result: Dataset[(String, Long)] = grouped.count()//聚合操作
    result.show()
  }

8.1.4 切分类型的操作

切分类型的操作主要包含:randomSplit、sample

(1)randomSplit

方法描述:randomSplit 会按照传入的权重随机将一个 Dataset 分为多个 Dataset, 传入 randomSplit 的数组有多少个权重, 最终就会生成多少个 Dataset, 这些权重的加倍和应该为 1, 否则将被标准化

    val ds = spark.range(15)
    //randomSplit:切多少分,权重多少
    val datasets: Array[Dataset[lang.Long]] = ds.randomSplit(Array(5,2,3))
    datasets.foreach(_.show())

(2)sample

方法描述:sample 会随机在 Dataset 中抽样

    val ds = spark.range(15)

    //sample 有放回
    ds.sample(withReplacement = false,fraction = 0.4).show()

8.1.5 排序类型的操作

排序类型的操作主要包含:orderBy、sort

(1)orderBy

方法描述:orderBy 配合 Column 的 API, 可以实现正反序排列

    val ds =  Seq(Person("张三",15),Person("张三",15),Person("李四",20)).toDS()
    ds.orderBy('age.desc).show()

(2)sort

方法描述:其实 orderBy 是 sort 的别名, 所以它们所实现的功能是一样的

    val ds =  Seq(Person("张三",15),Person("张三",15),Person("李四",20)).toDS()
    ds.sort('age.asc).show()

8.1.6 分区类型的操作

分区类型的操作主要包含:coalesce、repartitions

(1)coalesce

方法描述:减少分区, 此算子和 RDD 中的 coalesce 不同, Dataset 中的 coalesce 只能减少分区数, coalesce 会直接创建一个逻辑操作, 并且设置 Shuffle 为 false

val ds = spark.range(15)
ds.coalesce(1).explain(true)

(2)repartitions

方法描述:repartitions 有两个作用, 一个是重分区到特定的分区数, 另一个是按照某一列来分区, 类似于 SQL 中的 DISTRIBUTE BY

val ds = Seq(Person("zhangsan", 12), Person("zhangsan", 8), Person("lisi", 15)).toDS()
ds.repartition(4)
ds.repartition('name)

8.1.7 去重类型的操作

去重类型的操作主要包含:dropDuplicates、distinct

(1)dropDuplicates

方法描述:使用 dropDuplicates 可以去掉某一些列中重复的行

    val ds =  Seq(Person("张三",15),Person("张三",15),Person("李四",20)).toDS()
    ds.dropDuplicates("age").show()

(2)distinct

方法描述:当 dropDuplicates 中没有传入列名的时候, 其含义是根据所有列去重, dropDuplicates() 方法还有一个别名, 叫做 distinct

所以, 使用 distinct 也可以去重, 并且只能根据所有的列来去重

    val ds =  Seq(Person("张三",15),Person("张三",15),Person("李四",20)).toDS()
    ds.distinct().show()

8.1.8 集合类型的操作

集合类型的操作主要包含:except、intersect、union、limit

(1)except

方法描述:except 和 SQL 语句中的 except 一个意思, 是求得 ds1 中不存在于 ds2 中的数据, 其实就是差集

    val ds1 = spark.range(1,10)
    val ds2 = spark.range(5,15)

    //差集 ds1中去掉ds2中有的数据
    ds1.except(ds2).show()

(2)intersect

方法描述:求得两个集合的交集

    val ds1 = spark.range(1,10)
    val ds2 = spark.range(5,15)

    //交集
    ds1.intersect(ds2).show()

(3)union

方法描述:求得两个集合的并集

    val ds1 = spark.range(1,10)
    val ds2 = spark.range(5,15)

    //并集
    ds1.union(ds2).show()

(4)limit

方法描述:限制结果集数量

    val ds1 = spark.range(1,10)
    val ds2 = spark.range(5,15)

    //limit
    ds1.limit(3).show()

 

8.2 无类型操作

8.2.1 选择类型的操作

选择类型的操作主要包含:select、selectExpr、withColumn、withColumnRenamed

(1)select

方法描述:select 用来选择某些列出现在结果集中

(2)selectExpr

方法描述:在 SQL 语句中, 经常可以在 select 子句中使用 count(age), rand() 等函数, 在 selectExpr 中就可以使用这样的 SQL 表达式, 同时使用 select 配合 expr 函数也可以做到类似的效果

  val spark = SparkSession.builder().master("local[6]").appName("typed").getOrCreate()

  import spark.implicits._

  @Test
  def select():Unit={
    val ds =  Seq(Person("zhangsan",12),Person("lisi",15),Person("zhangsan",18)).toDS()
    //在Dataset中,select可以在任何位置调用
    ds.select('name).show()

    ds.selectExpr("sum(age)").show()

    import org.apache.spark.sql.functions._

    ds.select(expr("sum(age)")).show()
  }

(3)withColumn

方法描述:通过 Column 对象在 Dataset 中创建一个新的列或者修改原来的列

(4)withColumnRenamed

方法描述:修改列名

  @Test
  def column():Unit= {
    val ds = Seq(Person("zhangsan", 12), Person("lisi", 15), Person("zhangsan", 18)).toDS()

    import org.apache.spark.sql.functions._

    //如果想使用函数功能,有两种方式
    //1.使用function.xx   2.使用表达式,可以使用expr("") 随时随地编写表达式
    ds.withColumn("random",expr("rand()")).show()

    //重命名
    ds.withColumn("name_new",'name).show()

    ds.withColumn("name_jok",'name === "").show()

    ds.withColumnRenamed("name","new_name").show()
  }

 

8.2.2 剪切类型的操作

剪切类型的操作主要包含:drop

(1)drop

方法描述:剪掉某个列

import spark.implicits._
val ds = Seq(Person("zhangsan", 12), Person("zhangsan", 8), Person("lisi", 15)).toDS()
ds.drop('age).show()

8.2.3 聚合类型的操作

聚合类型的操作主要包含:groupBy

(1)groupBy

方法描述:按照给定的行进行分组

  @Test
  def groupBy():Unit = {
    val ds = Seq(Person("zhangsan", 12), Person("zhangsan", 8), Person("lisi", 15)).toDS()

    //为什么GroupByKey 是有类型的
    //最主要的原因是因为goupByKey 所生成的对象中的算子是有类型的
//    ds.groupByKey(x => x.name).mapValues()

    //为什么 GroupBy是无类型的
    //因为groupBy所生成的对象中的算子是无类型的,针对列进行处理的
    import org.apache.spark.sql.functions._
    ds.groupBy("name").agg(mean("age")).show()

  }

 

以上便是 SparkSQL关于数据操作中数据转换相关的算子用法.

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark SQLSpark生态系统中的一个组件,它提供了一种用于结构化数据处理的高级数据处理接口。Spark SQL支持使用SQL语言进行数据查询和处理,并且可以与Spark的其他组件(如Spark Streaming、MLlib等)无缝集成。Spark SQL还支持使用DataFrame API进行数据处理,这使得开发人员可以使用Scala、Java、Python和R等编程语言进行数据处理。Spark SQL还支持将数据存储在各种数据源中,如Hive、JSON、Parquet等。Spark SQL的主要优点是可以处理大规模的结构化数据,并且具有高性能和可扩展性。 ### 回答2: SparkSQL是Apache Spark中的一种组件,它用于处理结构化和半结构化数据。与传统的Spark核心功能相比,SparkSQL提供了更高级的数据处理工具,使得用户可以使用SQL查询和操作结构化数据SparkSQL的基本概念包括DataFrame和Dataset。DataFrame是强类型的分布式数据集,它可以看作是一个表,每一列都有一个名字和数据类型。Dataset是比DataFrame更加丰富的API,它可以以编程的方式进行查询和操作数据SparkSQL支持使用标准的SQL查询语言进行数据查询和聚合。用户可以编写SQL语句来过滤、聚合和排序数据,并通过SparkSQL将结果存储在DataFrame或Dataset中。 SparkSQL还支持多种数据格式的读取和写入,包括Parquet、Avro、JSON和CSV等。用户可以通过提供Schema来从这些格式中读取数据,并可以选择将数据以这些格式写入磁盘。 另外,SparkSQL还提供了与Hive的集成,使得用户可以使用Hive的元数据和UDF函数。用户可以通过SparkSQL查询Hive表,并将查询结果存储在Hive表中。 SparkSQL还支持缓存数据以提高查询性能。用户可以使用DataFrame或Dataset的persist()方法将数据持久化到内存或磁盘中,并可以通过调用unpersist()方法来释放缓存的数据。 总结来说,SparkSQL是Apache Spark中用于处理结构化和半结构化数据的组件,它提供了DataFrame和Dataset的概念,支持使用SQL语言进行数据查询和聚合,以及多种数据格式的读写,还具备与Hive的集成以及数据缓存等功能。 ### 回答3: Spark SQL是Apache Spark的一个模块,它提供了用于处理结构化数据SQL查询和集成,使得在Spark中可以方便地进行数据处理和分析。 Spark SQL的核心是DataFrames,它是一种可处理具有命名列的分布式数据集的数据结构。DataFrames可以由多种数据源创建,包括结构化数据、Parquet文件、JSON文件、Hive表等。与传统的RDD相比,DataFrames具有更高的性能和更强的优化能力,因为它们提供了类似于传统数据库的结构化查询API。 通过Spark SQL,我们可以使用标准的SQL查询语言来查询和操作DataFrames中的数据Spark SQL支持常见的SQL操作,如SELECT、JOIN、GROUP BY等,还支持用户自定义函数和聚合函数的定义。这使得开发人员可以使用熟悉的SQL语法来处理和分析数据,无需编写复杂的MapReduce或Spark程序。 除了SQL查询,Spark SQL还提供了用于将DataFrames转换为RDD的接口,以及将RDD转换为DataFrames的接口。这使得在需要深度定制数据处理逻辑时可以灵活地切换和使用两者之间的API。 总之,Spark SQL是一个强大而灵活的数据处理工具,它通过提供SQL查询和集成的方式,使得在Spark中可以方便地处理和分析结构化数据。它不仅提供了与传统数据库类似的性能和优化能力,还提供了与Spark的其他组件(如MLlib和GraphX)的无缝集成,使得在Spark平台上进行大规模数据处理变得更加简单和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值