Spark Session中的DataFrame类似于一张关系型数据表。在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现。

可以参考,Scala提供的DataFrame API。本文中的代码基于Spark-2.2的文档实现。

一、DataFrame对象的生成

  Spark-SQL可以以其他RDD对象、parquet文件、json文件、Hive表,以及通过JDBC连接到其他关系型数据库作为数据源来生成DataFrame对象。本文将以MySQL数据库为数据源,生成DataFrame对象后进行相关的DataFame之上的操作。 
  文中生成DataFrame的代码如下:

val ss = SparkSession.builder()
          .appName("ta")
          .master("local[4]")
          .config("spark.mongodb.input.uri","mongodb://username:password@192.168.1.3:27017/log.")
          .config("spark.mongodb.output.uri","mongodb://username:password@192.168.1.3:27017/log")
          .getOrCreate()

1.读取mysql数据   

 val url = "jdbc:mysql://m000:3306/test"
 val jdbcDF = ss.read.format( "jdbc" ).options(Map( "url" -> url,"user" -> "xxx","password" -> "xxx", "dbtable" -> "xxx" )).load()

2.读取SqlServer数据   

 val sqlUrl="jdbc:sqlserver://192.168.1.3:1433;DatabaseName=mytable;username=xxxx;password=xxx"
 val data2DF = ss.read.format("jdbc").options( Map("url" -> sqlsUrl, "dbtable" -> "TableName")).load()

3.读取MongoDB数据

 val data1DF = MongoSpark.load(ss, ReadConfig(Map("collection" -> "TableName"), Some(ReadConfig(ss))))

1、show:展示数据

  以表格的形式在输出中展示jdbcDF中的数据,类似于select * from spark_sql_test的功能。 
  show方法有四种调用方式,分别为, 
(1)show 
  只显示前20条记录。且过长的字符串会被截取
  示例:jdbcDF.show

(2)show(numRows: Int)

  显示numRows条 
  示例:jdbcDF.show(3)

(3)show(truncate: Boolean) 
  是否截取20个字符,默认为true。 
  示例:jdbcDF.show(false)  

(4)show(numRows: Int, truncate: Int) 
  显示记录条数,以及截取字符个数,为0时表示不截取
  示例:jdbcDF.show(3, 0)

2、collect:获取所有数据到数组

  不同于前面的show方法,这里的collect方法会将jdbcDF中的所有数据都获取到,并返回一个Array对象。

jdbcDF.collect()

  结果数组包含了jdbcDF的每一条记录,每一条记录由一个GenericRowWithSchema对象来表示,可以存储字段名及字段值。

3、collectAsList:获取所有数据到List

  功能和collect类似,只不过将返回结构变成了List对象,使用方法如下

jdbcDF.collectAsList()

4、describe(cols: String*):获取指定字段的统计信息

  这个方法可以动态的传入一个或多个String类型的字段名,结果仍然为DataFrame对象,用于统计数值类型字段的统计值,比如count, mean, stddev, min, max等。 
  使用方法如下,其中c1字段为字符类型,c2字段为整型,c4字段为浮点型

jdbcDF .describe("c1" , "c2", "c4" ).show()

结果如下:

5、first, head, take, takeAsList:获取若干行记录

  这里列出的四个方法比较类似,其中 
  (1)first获取第一行记录 
  (2)head获取第一行记录,head(n: Int)获取前n行记录 
  (3)take(n: Int)获取前n行数据 
  (4)takeAsList(n: Int)获取前n行数据,并以List的形式展现 
  以Row或者Array[Row]的形式返回一行或多行数据。firsthead功能相同。 
  taketakeAsList方法会将获得到的数据返回到Driver端,所以,使用这两个方法时需要注意数据量,以免Driver发生OutOfMemoryError

  使用和结果略。

二、DataFrame对象上的条件查询和join等操作

  以下返回为DataFrame类型的方法,可以连续调用。

1、where条件相关

(1)where(conditionExpr: String):SQL语言中where关键字后的条件 
  传入筛选条件表达式,可以用andor。得到DataFrame类型的返回结果, 
  示例:

jdbcDF .where("id = 1 or c1 = 'b'" ).show()

(2)filter:根据字段进行筛选 
  传入筛选条件表达式,得到DataFrame类型的返回结果。和where使用条件相同 
  示例:jdbcDF .filter("id = 1 or c1 = 'b'" ).show()

 

2、查询指定字段

(1)select:获取指定字段值 
  根据传入的String类型字段名,获取指定字段的值,以DataFrame类型返回 
  示例:

jdbcDF.select( "id" , "c3" )

还有一个重载的select方法,不是传入String类型参数,而是传入Column类型参数。可以实现select id, id+1 from test这种逻辑。

jdbcDF.select(jdbcDF( "id" ), jdbcDF( "id") +  ).show( false)

 能得到Column类型的方法是apply以及col方法,一般用apply方法更简便。

(2)selectExpr:可以对指定字段进行特殊处理 
  可以直接对指定字段调用UDF函数,或者指定别名等。传入String类型参数,得到DataFrame对象。 
  示例,查询id字段,c3字段取别名timec4字段四舍五入:

jdbcDF .selectExpr("id" , "c3 as time" , "round(c4)" ).show(false)

(3)col:获取指定字段 
  只能获取一个字段,返回对象为Column类型。

  val idCol = jdbcDF.col(“id”)

(4)apply:获取指定字段 
  只能获取一个字段,返回对象为Column类型 
  示例:

val idCol1 = jdbcDF.apply("id")
val idCol2 = jdbcDF("id")

(5)drop:去除指定字段,保留其他字段 
  返回一个新的DataFrame对象,其中不包含去除的字段,一次只能去除一个字段。 
  示例:

jdbcDF.drop("id")
jdbcDF.drop(jdbcDF("id"))

3、limit

  limit方法获取指定DataFrame的前n行记录,得到一个新的DataFrame对象。和takehead不同的是,limit方法不是Action操作。

jdbcDF.limit()
、order by
()orderBy和sort:按指定字段排序,默认为升序
  示例1,按指定字段排序。加个-表示降序排序。sort和orderBy使用方法相同
jdbcDF.orderBy(- jdbcDF("c4")).show(false) 只能对数字类型和日期类型生效
// 或者
jdbcDF.orderBy(jdbcDF("c4").desc).show(false)

()sortWithinPartitions
  和上面的sort方法功能类似,区别在于sortWithinPartitions方法返回的是按Partition排好序的DataFrame对象。

5、group by

(1)groupBy:根据字段进行group by操作 
  groupBy方法有两种调用方式,可以传入String类型的字段名,也可传入Column类型的对象。 
  使用方法如下,

jdbcDF .groupBy("c1" )
jdbcDF.groupBy( jdbcDF( "c1"))
()cube和rollup:group by的扩展
  功能类似于SQL中的group by cube/rollup

(3)GroupedData对象 
  该方法得到的是GroupedData类型对象,在GroupedData的API中提供了group by之后的操作,比如,

    • max(colNames: String*)方法,获取分组中指定字段或者所有的数字类型字段的最大值,只能作用于数字型字段
    • min(colNames: String*)方法,获取分组中指定字段或者所有的数字类型字段的最小值,只能作用于数字型字段
    • mean(colNames: String*)方法,获取分组中指定字段或者所有的数字类型字段的平均值,只能作用于数字型字段
    • sum(colNames: String*)方法,获取分组中指定字段或者所有的数字类型字段的和值,只能作用于数字型字段
    • count()方法,获取分组中的元素个数

        运行结果示例: 
        count

max

  • 这里面比较复杂的是以下两个方法, 
    agg,pivot该方法和下面介绍的类似,可以用于对指定字段进行聚合操作。

6、distinct

(1)distinct:返回一个不包含重复记录的DataFrame 
  返回当前DataFrame中不重复的Row记录。该方法和接下来的dropDuplicates()方法不传入指定字段时的结果相同。 
  示例:

jdbcDF.distinct()

(2)dropDuplicates:根据指定字段去重 
  根据指定字段去重。类似于select distinct a, b操作 
  示例:

jdbcDF.dropDuplicates(Seq("c1"))

7、聚合

  聚合操作调用的是agg方法,该方法有多种调用方式。一般与groupBy方法配合使用。 
  以下示例其中最简单直观的一种用法,对id字段求最大值,对c4字段求和

jdbcDF.agg("id" -> "max", "c4" -> "sum")

8、union

  union方法:对两个DataFrame进行合并
  示例:

jdbcDF.union(jdbcDF.limit())

9、join

  重点来了。在SQL语言中用得很多的就是join操作,DataFrame中同样也提供了join的功能。 
  接下来隆重介绍join方法。在DataFrame中提供了六个重载的join方法。 
(1)、笛卡尔积

joinDF1.join(joinDF2)

(2)、using一个字段形式 
  下面这种join类似于a join b using column1的形式,需要两个DataFrame中有相同的一个列名,

joinDF1.join(joinDF2, "id")

(3)、using多个字段形式 
  除了上面这种using一个字段的情况外,还可以using多个字段,如下

joinDF1.join(joinDF2, Seq("id", "name"))

(4)、指定join类型 
  两个DataFrame的join操作有inner, outer,full,full_outer,left, left_outer, right_outer, leftsemi类型。在上面的using多个字段的join情况下,可以写第三个String类型参数,指定join的类型,如下所示

joinDF1.join(joinDF2, Seq("id", "name"), "inner")

(5)、使用Column类型来join 
  如果不用using模式,灵活指定join字段的话,可以使用如下形式

joinDF1.join(joinDF2 , joinDF1("id" ) === joinDF2( "t1_id"))

(6)、在指定join字段同时指定join类型 
  如下所示

joinDF1.join(joinDF2 , joinDF1("id" ) === joinDF2( "t1_id"), "inner")

10、获取指定字段统计信息

 stat方法可以用于计算指定字段或指定字段之间的统计信息,比如方差,协方差等。这个方法返回一个DataFramesStatFunctions类型对象。 
 下面代码演示根据c4字段,统计该字段值出现频率在30%以上的内容。在jdbcDF中字段c1的内容为"a, b, a, c, d, b"。其中ab出现的频率为2 / 6,大于0.3

jdbcDF.stat.freqItems(Seq ("c1") , 0.3).show()

11、获取两个DataFrame中共有的记录

  intersect方法可以计算出两个DataFrame中相同的记录,

jdbcDF.intersect(jdbcDF.limit()).show(false)

12、获取一个DataFrame中有另一个DataFrame中没有的记录

  示例:

jdbcDF.except(jdbcDF.limit()).show(false)

13、操作字段名

(1)withColumnRenamed:重命名DataFrame中的指定字段名 
  如果指定的字段名不存在,不进行任何操作。下面示例中将jdbcDF中的id字段重命名为idx

jdbcDF.withColumnRenamed( "id" , "idx" )

(2)withColumn:往当前DataFrame中新增一列 
  whtiColumn(colName: String , col: Column)方法根据指定colName往DataFrame中新增一列,如果colName已存在,则会覆盖当前列。 
  以下代码往jdbcDF中新增一个名为id2的列,

jdbcDF.withColumn("id2", jdbcDF("id")).show( false)

14、行转列

  有时候需要根据某个字段内容进行分割,然后生成多行,这时可以使用explode方法 
  下面代码中,根据c3字段中的空格将字段内容进行分割,分割的内容存储在新的字段c3_中,如下所示

jdbcDF.explode( "c3" , "c3_" ){time: String => time.split( " " )}

Spark 2.2 DataFrame的一些算子操作的更多相关文章

  1. spark2.2 DataFrame的一些算子操作

    Spark Session中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的Dat ...

  2. Spark RDD、DataFrame原理及操作详解

    RDD是什么? RDD (resilientdistributed dataset),指的是一个只读的,可分区的分布式数据集,这个数据集的全部或部分可以缓存在内存中,在多次计算间重用. RDD内部可以 ...

  3. spark结构化数据处理:Spark SQL、DataFrame和Dataset

    本文讲解Spark的结构化数据处理,主要包括:Spark SQL.DataFrame.Dataset以及Spark SQL服务等相关内容.本文主要讲解Spark 1.6.x的结构化数据处理相关东东,但 ...

  4. Spark入门之DataFrame/DataSet

    目录 Part I. Gentle Overview of Big Data and Spark Overview 1.基本架构 2.基本概念 3.例子(可跳过) Spark工具箱 1.Dataset ...

  5. Spark SQL 之 DataFrame

    Spark SQL 之 DataFrame 转载请注明出处:http://www.cnblogs.com/BYRans/ 概述(Overview) Spark SQL是Spark的一个组件,用于结构化 ...

  6. Spark官方1 ---------Spark SQL和DataFrame指南(1.5.0)

    概述 Spark SQL是用于结构化数据处理的Spark模块.它提供了一个称为DataFrames的编程抽象,也可以作为分布式SQL查询引擎. Spark SQL也可用于从现有的Hive安装中读取数据 ...

  7. Spark RDD、DataFrame和DataSet的区别

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   转载请标明出处:小帆的帆的专栏 RDD 优点: 编译时类型安全 编译时就能检查出类型错误 面向对象的编程风格 直接通过类 ...

  8. 转】Spark SQL 之 DataFrame

    原博文出自于: http://www.cnblogs.com/BYRans/p/5003029.html 感谢! Spark SQL 之 DataFrame 转载请注明出处:http://www.cn ...

  9. Spark学习之路(八)—— Spark SQL 之 DataFrame和Dataset

    一.Spark SQL简介 Spark SQL是Spark中的一个子模块,主要用于操作结构化数据.它具有以下特点: 能够将SQL查询与Spark程序无缝混合,允许您使用SQL或DataFrame AP ...

随机推荐

  1. PyQt的Layout的比例化分块。

    一. QGridLayout: // 列比 第0列与第1列之比为 1:2 layout2p1 -> setColumnStretch(0, 1); layout2p1 -> setColu ...

  2. python 处理抓取网页乱码

    python 处理抓取网页乱码问题一招鲜   相信用python的人一定在抓取网页时,被编码问题弄晕过一阵 前几天写了一个测试网页的小脚本,并查找是否包含指定的信息. 在html = urllib2. ...

  3. 详谈JavaScript 匿名函数及闭包

    1.匿名函数函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种:这 ...

  4. jQuery实现鼠标悬停显示提示信息窗口的方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. Unity中对SQL数据库的操作

    在Unity中,我们有时候需要连接数据库来达到数据的读取与储存.而在.NET平台下,ADO.NET为我们提供了公开数据访问服务的类.客户端应用程序可以使用ADO.NET来连接到数据源,并查询,添加,删 ...

  6. [转]这五种方法前四种方法只支持IE浏览器,最后一个方法支持当前主流的浏览器(火狐,IE,Chrome,Opera,Safari)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. Spring_day01--Spring的bean管理(xml方式)_属性注入介绍

    Spring的bean管理(xml方式) Bean实例化的方式 1 在spring里面通过配置文件 创建对象 2 bean实例化(创建对象)三种方式实现 第一种 使用类的无参数构造创建(重点) Use ...

  8. Spring_day01--课程安排_Spring概念_IOC操作&IOC底层原理&入门案例_配置文件没有提示问题

    Spring_day01 Spring课程安排 今天内容介绍 Spring概念 Spring的ioc操作 IOC底层原理 IOC入门案例 配置文件没有提示问题 Spring的bean管理(xml方式) ...

  9. 剑指 offer set 28 实现 Singleton 模式

    singleton 模式又称单例模式, 它能够保证只有一个实例. 在多线程环境中, 需要小心设计, 防止两个线程同时创建两个实例. 解法 1. 能在多线程中工作但效率不高 public sealed ...

  10. java基础---->final关键字的使用

    这里介绍一些java基础关于final的使用,文字说明部分摘自java语言规范.心甘情愿这四个字,透着一股卑微,但也有藏不住的勇敢. Final关键字的说明 一.关于final变量规范说明 .A fi ...