设为首页 加入收藏

TOP

sparksql中dataframe的用法
2018-12-14 01:27:47 】 浏览:52
Tags:sparksql dataframe 用法
版权声明:原创文章,转载请注明出处 https://blog.csdn.net/xianpanjia4616/article/details/84891231

Spark SQL 是 Spark 处理结构化数据的一个模块.与基础的 Spark RDD API 不同, Spark SQL 提供了查询结构化数据及计算结果等信息的接口.在内部, Spark SQL 使用这个额外的信息去执行额外的优化.有几种方式可以跟 Spark SQL 进行交互, 包括 SQL 和 Dataset API.当使用相同执行引擎进行计算时, 无论使用哪种 API / 语言都可以快速的计算.这种统一意味着开发人员能够在基于提供最自然的方式来表达一个给定的 transformation API 之间实现轻松的来回切换不同的 .

该页面所有例子使用的示例数据都包含在 Spark 的发布中, 并且可以使用spark-shell,pysparkshell, 或者sparkRshell来运行.

Spark SQL 的功能之一是执行 SQL 查询.Spark SQL 也能够被用于从已存在的 Hive 环境中读取数据.更多关于如何配置这个特性的信息, 请参考Hive 表这部分. 当以另外的编程语言运行SQL 时, 查询结果将以Dataset/DataFrame的形式返回.您也可以使用命令行或者通过JDBC/ODBC与 SQL 接口交互.

Datasets and DataFrames

一个 Dataset 是一个分布式的数据集合 Dataset 是在 Spark 1.6 中被添加的新接口, 它提供了 RDD 的优点(强类型化, 能够使用强大的 lambda 函数)与Spark SQL执行引擎的优点.一个 Dataset 可以从 JVM 对象来构造并且使用转换功能(map, flatMap, filter, 等等). Dataset API 在ScalaJava是可用的.Python 不支持 Dataset API.但是由于 Python 的动态特性, 许多 Dataset API 的优点已经可用了 (也就是说, 你可能通过 name 天生的row.columnName属性访问一行中的字段).这种情况和 R 相似.

一个 DataFrame 是一个Dataset组成的指定列.它的概念与一个在关系型数据库或者在 R/Python 中的表是相等的, 但是有很多优化. DataFrames 可以从大量的sources中构造出来, 比如: 结构化的文本文件, Hive中的表, 外部数据库, 或者已经存在的 RDDs. DataFrame API 可以在 Scala, Java,Python, 和R中实现. 在 Scala 和 Java中, DataFrame 由 DataSet 中的RowS(多个 Row)来表示. 在the Scala API中,DataFrame仅仅是一个Dataset[Row]类型的别名. 然而, 在Java API中, 用户需要去使用Dataset<Row>去代表一个DataFrame.

dataframe的api是非常丰富的,有很多种写法,写起来也很方便,可以根据自己的喜好去写,从下面的demo中你也会发现这一点的.

下面看一下dataframe的一些常用的操作,写的不是太全,都是经常用到的,代码里面有详细的注释:

package spark

import groovy.sql.DataSet
import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.{DataFrame, Row, SparkSession}

object sparkSession {
  case class Person(name:String,age:BigInt)
  Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder()
      .master("local[4]")
      .appName("Spark SQL Example")
      .getOrCreate()
    //读取json文件,返回一个dataframe;
    val df = spark.read.json("D:\\people.json")
    import spark.implicits._
    //查看DataFrame中的内容,默认显示20行;
    df.show()
    //----------------------dataframe和dataSet相互转换-----------------------------------
    // val df:DataFrame = DataSet[Row]  //dataframe和dataSet的关系;
    val ds = df.as[Person]
    val ds_1 = df.toJSON
    val df_new = ds.toDF()
    //----------------------------------------------------------------------------------
    //打印DataFrame的Schema信息;可以理解为模型;
    df.printSchema()
    //查看DataFrame部分列中的内容,age
    df.select("age").show()
    //查看DataFrame部分列中的内容,age+1
    df.select($"name",$"age"+1).show
    //另外一种写法;查看age和name;
    df.select(df("age"),df("name")).show()
    //过滤age大于20的,显示10行;
    df.filter($"age" > 20).show(10)
    //统计年龄大于20的人数;
    df.filter(df("age") > 20).count()
    //按年龄进行分组,统计人数;
    df.groupBy("name").count().show()
    //collect方法会将df中的所有数据都获取到,并返回一个Row类型的Array对象
    df.collect().foreach(println)
    //和上面的类似,返回一个Row类型的List集合;
    val list = df.collectAsList()
    //获取指定字段的统计信息;
    df.describe("name","age").show()
    //跟sql语句的where条件一样;
    df.where("age = 18 and name = 'jason'").show()
    //根据某个字段筛选;
    df.filter("name = 'jason'").show()
    //获取指定的字段可以对字段做一些特殊的操作,可以写别名;
    df.selectExpr("age","name as n").show()
    //获取指定的字段,注意这个一次只能获取一个字段;
    val age = df.col("age")
    println(age)
    //和上面的一样,也是获取某个字段;
    val name = df.apply("name")
    println(name)
    //删除指定的字段;
    df.drop("age").show()
    //跟sql的limit一样,显示前几行;
    df.limit(5).show()
    //根据某个字段排序;
    df.orderBy(df("age").desc).show()
    //按照partition进行排序;
    df.sortWithinPartitions("age").show()
    //跟sql里面的一样,根据某个字段分组;
    val groupby_name = df.groupBy("name").count().show()
    //结合groupby做一些聚合操作;
    df.groupBy("age").max().show()
    //去重;
    df.distinct().show()
    //指定字段去重;
    df.dropDuplicates("name").show()
    //聚合操作;
    df.agg("age"-> "max","age"-> "min").show()
    //对结果叠加;
    df.union(df).show()
    //跟sql里面的join一样支持,left join,right join,inner join,这个操作非常的丰富,这里就不在一一列举了;
    df.join(df,Seq("age"),"left").show()
    //获取两个df中相同的数据,相当于inner join;
    df.intersect(df).show()
    //对指定字段重命名;
    df.withColumnRenamed("name","name1").show()
    //增加新的字段,默认显示为null
    df.withColumn("name1",df("age")).show()
    //前几天有人问我增加新的字段显示为0,怎么写选择一列数值类型的乘以0就可以了;
    df.withColumn("name2",df("age")*0).show()
  }
}

执行的结果如下:

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
+---+-----+

root
 |-- age: long (nullable = true)
 |-- name: string (nullable = true)

+---+
|age|
+---+
| 18|
| 30|
| 19|
| 18|
| 30|
| 19|
| 18|
| 30|
| 19|
| 18|
| 30|
| 19|
+---+

+-----+---------+
| name|(age + 1)|
+-----+---------+
|jason|       19|
| Andy|       31|
|  jim|       20|
|jason|       19|
| Andy|       31|
|  jim|       20|
|jason|       19|
| Andy|       31|
|  jim|       20|
|jason|       19|
| Andy|       31|
|  jim|       20|
+-----+---------+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
+---+-----+

+---+----+
|age|name|
+---+----+
| 30|Andy|
| 30|Andy|
| 30|Andy|
| 30|Andy|
+---+----+

+-----+-----+
| name|count|
+-----+-----+
|jason|    4|
| Andy|    4|
|  jim|    4|
+-----+-----+

[18,jason]
[30,Andy]
[19,jim]
[18,jason]
[30,Andy]
[19,jim]
[18,jason]
[30,Andy]
[19,jim]
[18,jason]
[30,Andy]
[19,jim]
+-------+----+------------------+
|summary|name|               age|
+-------+----+------------------+
|  count|  12|                12|
|   mean|null|22.333333333333332|
| stddev|null|5.6782412983620425|
|    min|Andy|                18|
|    max| jim|                30|
+-------+----+------------------+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 18|jason|
| 18|jason|
| 18|jason|
+---+-----+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 18|jason|
| 18|jason|
| 18|jason|
+---+-----+

+---+-----+
|age|    n|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
+---+-----+

age
name
+-----+
| name|
+-----+
|jason|
| Andy|
|  jim|
|jason|
| Andy|
|  jim|
|jason|
| Andy|
|  jim|
|jason|
| Andy|
|  jim|
+-----+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
+---+-----+

+---+-----+
|age| name|
+---+-----+
| 30| Andy|
| 30| Andy|
| 30| Andy|
| 30| Andy|
| 19|  jim|
| 19|  jim|
| 19|  jim|
| 19|  jim|
| 18|jason|
| 18|jason|
| 18|jason|
| 18|jason|
+---+-----+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 18|jason|
| 18|jason|
| 18|jason|
| 19|  jim|
| 19|  jim|
| 19|  jim|
| 19|  jim|
| 30| Andy|
| 30| Andy|
| 30| Andy|
| 30| Andy|
+---+-----+

+-----+-----+
| name|count|
+-----+-----+
|jason|    4|
| Andy|    4|
|  jim|    4|
+-----+-----+

+---+--------+
|age|max(age)|
+---+--------+
| 19|      19|
| 18|      18|
| 30|      30|
+---+--------+

+---+-----+
|age| name|
+---+-----+
| 19|  jim|
| 30| Andy|
| 18|jason|
+---+-----+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
+---+-----+

+--------+--------+
|max(age)|min(age)|
+--------+--------+
|      30|      18|
+--------+--------+

+---+-----+
|age| name|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
+---+-----+
only showing top 20 rows

+---+-----+-----+
|age| name| name|
+---+-----+-----+
| 18|jason|jason|
| 18|jason|jason|
| 18|jason|jason|
| 18|jason|jason|
| 30| Andy| Andy|
| 30| Andy| Andy|
| 30| Andy| Andy|
| 30| Andy| Andy|
| 19|  jim|  jim|
| 19|  jim|  jim|
| 19|  jim|  jim|
| 19|  jim|  jim|
| 18|jason|jason|
| 18|jason|jason|
| 18|jason|jason|
| 18|jason|jason|
| 30| Andy| Andy|
| 30| Andy| Andy|
| 30| Andy| Andy|
| 30| Andy| Andy|
+---+-----+-----+
only showing top 20 rows

+---+-----+
|age| name|
+---+-----+
| 19|  jim|
| 30| Andy|
| 18|jason|
+---+-----+

+---+-----+
|age|name1|
+---+-----+
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
| 18|jason|
| 30| Andy|
| 19|  jim|
+---+-----+

+---+-----+-----+
|age| name|name1|
+---+-----+-----+
| 18|jason|   18|
| 30| Andy|   30|
| 19|  jim|   19|
| 18|jason|   18|
| 30| Andy|   30|
| 19|  jim|   19|
| 18|jason|   18|
| 30| Andy|   30|
| 19|  jim|   19|
| 18|jason|   18|
| 30| Andy|   30|
| 19|  jim|   19|
+---+-----+-----+

+---+-----+-----+
|age| name|name2|
+---+-----+-----+
| 18|jason|    0|
| 30| Andy|    0|
| 19|  jim|    0|
| 18|jason|    0|
| 30| Andy|    0|
| 19|  jim|    0|
| 18|jason|    0|
| 30| Andy|    0|
| 19|  jim|    0|
| 18|jason|    0|
| 30| Andy|    0|
| 19|  jim|    0|
+---+-----+-----+

当然了还有很多方法,这里就列举了一些平时经常用到的.

如果有写的不对的地方,欢迎大家指正,如果有什么疑问,可以加QQ群:340297350,谢谢

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇spark_core 下一篇spark核心概念及入门

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目