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-shellpyspark shell, 或者 sparkR shell来运行.

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 在Scala 和 Java是可用的.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,谢谢

猜你喜欢

转载自blog.csdn.net/xianpanjia4616/article/details/84891231
今日推荐