Spark SQL大数据分析快速上手-DataFrame应用体验

【图书介绍】《Spark SQL大数据分析快速上手》-CSDN博客

《Spark SQL大数据分析快速上手》【摘要 书评 试读】- 京东图书

大数据与数据分析_夏天又到了的博客-CSDN博客

本节主要介绍如何使用DataFrame进行编程。

4.1.1 SparkSession

在旧版本中,Spark SQL提供两种SQL查询起始点:一个叫作SQLContext,用于Spark自己提供的SQL查询;一个叫作HiveContext,用于连接Hive的查询。

SparkSession是Spark最新的SQL查询起始点,实质上是SQLContext和HiveContext的组合。因此,在SQLContext和HiveContext上可用的API,在SparkSession上同样可以使用。

SparkSession内部封装了SparkContext,所以计算实际上是由SparkContext完成的。

当我们使用Spark Shell的时候,Spark会自动创建一个叫作spark的SparkSession,就像以前可以自动获取一个sc来表示SparkContext一样,如图4-1所示。

图4-1 自动创建SparkSession

4.1.2 DataFrame应用

Spark SQL的DataFrame API允许我们使用DataFrame而不必去注册临时表或者生成SQL表达式。DataFrame API既有转换操作,也有行动操作;DataSet API则提供了更加函数式的API。

1. 创建DataFrame

有了SparkSession之后,可以通过以下3种方式来创建DataFrame:

  • 通过Spark的数据源来创建。
  • 通过已知的RDD来创建。
  • 通过查询一个Hive表来创建。

Spark支持的数据源如图4-2所示。

图4-2 Spark支持的数据源

通过Spark数据源创建DataFrame的代码如下:

复制代码
// 读取 JSON 文件
scala> val df = spark.read.json("/opt/module/spark-local/examples/src/main/ resources/employees.json")
df: org.apache.spark.sql.DataFrame = [name: string, salary: bigint]

// 展示结果
scala> df.show
+-------+------+
|   name|salary|
+-------+------+
|Michael|  3000|
|   Andy|  4500|
| Justin|  3500|
|  Berta|  4000|
+-------+------+

其中,employees.json文件内容如下:

复制代码
{"name":"Michael", "salary":3000}
{"name":"Andy", "salary":4500}
{"name":"Justin", "salary":3500}
{"name":"Berta", "salary":4000}
2. DataFrame语法风格

1)SQL语法风格

SQL语法风格是指我们查询数据的时候可以使用SQL语句。这种SQL语句风格的查询必须有临时视图或者全局视图来辅助。

创建视图的数据来源于people.json,其内容如下:

复制代码
{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}

创建临时视图的代码如下:

复制代码
scala> val df = spark.read.json("/opt/module/spark-local/examples/ src/main/resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> df.createOrReplaceTempView("people")

scala> spark.sql("select * from people").show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

创建全局视图的代码如下:

复制代码
scala> val df = spark.read.json("/opt/module/spark-local/examples/src/main/ resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> df.createGlobalTempView("people")

scala> spark.sql("select * from global_temp.people")
res31: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> res31.show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

2)DSL语法风格

DataFrame提供一个特定领域语言(domain-specific language,DSL)去管理结构化的数据。可以在Scala、Java、Python和R中使用DSL。使用DSL语法风格就不必创建临时视图了。

(1)查看schema信息,示例代码如下:

复制代码
scala> val df = spark.read.json("/opt/module/spark-local/examples/src/main/ resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> df.printSchema
root
|-- age: long (nullable = true)
|-- name: string (nullable = true)

(2)使用DSL查询,示例代码如下:

只查询name列数据:

复制代码
scala> df.select($"name").show
+-------+
|   name|
+-------+
|Michael|
|   Andy|
| Justin|
+-------+


scala> df.select("name").show
+-------+
|   name|
+-------+
|Michael|
|   Andy|
| Justin|

查询name和age列数据:

复制代码
scala> df.select("name", "age").show
+-------+----+
|   name| age|
+-------+----+
|Michael|null|
|   Andy|  30|
| Justin|  19|
+-------+----+

查询name和age + 1的数据:

复制代码
scala> df.select($"name", $"age" + 1).show
+-------+---------+
|   name|(age + 1)|
+-------+---------+
|Michael|     null|
|   Andy|       31|
| Justin|       20|
+-------+---------+

查询age大于20的数据:

复制代码
scala> df.filter($"age" > 21).show
+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+

按照age分组,查看数据条数:

复制代码
scala> df.groupBy("age").count.show
+----+-----+
| age|count|
+----+-----+
|  19|    1|
|null|    1|
|  30|    1|
+----+-----+
3. RDD和DataFrame的交互

1)从RDD到DataFrame

涉及RDD、DataFrame、DataSet之间的操作时,需要进行导入,即import spark.implicits._。这里的spark不是包名,而是表示SparkSession的那个对象,所以必须先创建SparkSession对象再导入;implicits是一个内部对象。

首先创建一个RDD:

复制代码
scala> val rdd1 = sc.textFile("/opt/module/spark-local/examples/src/main/resources/people.txt")
rdd1: org.apache.spark.rdd.RDD[String] = /opt/module/spark-local/examples/src/main/resources/people.txt MapPartitionsRDD[10] at textFile at <console>:24

然后进行转换,转换有3种方法:手动转换、通过样例类反射转换和通过API的方式转换。

(1)手动转换。

示例代码如下:

复制代码
scala> val rdd2 = rdd1.map(line => { val paras = line.split(", "); (paras(0), paras(1).toInt)})
rdd2: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[11] at map at <console>:26

// 转换为DataFrame的时候手动指定每个数据字段名
scala> rdd2.toDF("name", "age").show
+-------+---+
|   name|age|
+-------+---+
|Michael| 29|
|   Andy| 30|
| Justin| 19|
+-------+---+

(2)通过样例类反射转换。

首先创建样例类:

复制代码
scala> case class People(name :String, age: Int)
defined class People

然后使用样例把 RDD 转换成DataFrame:

复制代码
scala> val rdd2 = rdd1.map(line => { val paras = line.split(", "); People(paras(0), paras(1).toInt) })
rdd2: org.apache.spark.rdd.RDD[People] = MapPartitionsRDD[6] at map at <console>:28

scala> rdd2.toDF.show
+-------+---+
|   name|age|
+-------+---+
|Michael| 29|
|   Andy| 30|
| Justin| 19|
+-------+---+

(3)通过API的方式转换。

通过API方式转换不能在spark命令行下进行,需要编写完整的Scala程序代码,示例代码 如下:

代码4-1 DataFrameDemo.scala

复制代码
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

object DataFrameDemo {
    def main(args: Array[String]): Unit = {
        val spark: SparkSession = SparkSession.builder()
            .master("local[*]")
            .appName("Word Count")
            .getOrCreate()
        val sc: SparkContext = spark.sparkContext
        val rdd: RDD[(String, Int)] = sc.parallelize(Array(("lisi", 10), ("zs", 20), ("zhiling", 40)))
        // 映射出来一个 RDD[Row], 因为 DataFrame其实就是 DataSet[Row]
        val rowRdd: RDD[Row] = rdd.map(x => Row(x._1, x._2))
        // 创建 StructType 类型
        val types = StructType(Array(StructField("name", StringType), StructField("age", IntegerType)))
        val df: DataFrame = spark.createDataFrame(rowRdd, types)
        df.show

    }
}

2)从DataFrame到RDD

直接调用DataFrame的rdd方法就能完成转换。示例代码如下:

复制代码
scala> val df = spark.read.json("/opt/module/spark-local/examples/src/main/resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

scala> val rdd = df.rdd
rdd: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = MapPartitionsRDD[6] at rdd at <console>:25

scala> rdd.collect
res0: Array[org.apache.spark.sql.Row] = Array([null,Michael], [30,Andy], [19,Justin])
相关推荐
计算机毕业编程指导师11 小时前
【计算机毕设推荐】Python+Spark卵巢癌风险数据可视化系统完整实现 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
hadoop·python·计算机·数据挖掘·spark·毕业设计·卵巢癌
极光代码工作室12 小时前
基于大数据的校园消费行为分析系统
大数据·hadoop·python·数据分析·spark
whuang0942 天前
腾讯云 emr 无法以cosn 写入云存储
spark
howard20053 天前
2.4.3 集群模式运行Spark项目
spark·项目打包·提交运行
孤雪心殇3 天前
快速上手数仓基础知识
数据仓库·hive·spark
渣渣盟3 天前
Spark 性能调优实战:从开发到生产落地
javascript·ajax·spark
渣渣盟4 天前
大数据技术栈全景图:从零到一的入门路线(深度实战版)
大数据·hadoop·python·flink·spark
DolphinScheduler社区5 天前
DolphinScheduler 3.3.2 如何调用 DataX 3.0 + SeaTunnel 2.3.12?附 Demo演示!
java·spark·apache·海豚调度·大数据工作流调度
Leo.yuan5 天前
数据仓库是什么?数据仓库和大数据平台、数据湖、数据中台、湖仓一体有什么区别?
大数据·数据仓库·spark
heiqizero6 天前
Spark RDD动作算子
spark