spark sql Dataset&Dataframe算子大全

目录

 

Dataset&Dataframe

RDD,Dataset,Dataframe互相转换

Dataset&Dataframe算子

show()

na()    返回包含null值的行

stat()

sortWithinPartitions()

sort()&order by()

hint()

selectExpr()

filter&where

groupBy&rollup&cube

reduce

groupByKey()

agg()

limit(n:Int)

union

intersect()

except()

sample()

randomSplit()

flatMap&explode

withColumn

 withColumnRenamed

drop

dropDuplicates()

describe(cols: String*): DataFrame

head(n: Int): Array[T]&head()&first()&take()&takeAsList

map&mapPartitions

collect()&collectAsList()&toLocalIterator()

count()


Dataset&Dataframe

type DataFrame = Dataset[Row]

DataFrame每一行类型为Row,DataSet就没这限制了。

//查hive表
val df=spark.sql("select date,status,api from data.api")//df的类型为sql.Dataframe

val ds1=df.map(ele=>(ele.getString(0)))
val ds2=df.map(ele=>(ele.getString(0),ele.getLong(1),ele.getString(2)))
//元素ele的类型为Row,获取值必须调用get()或者get类型()方法,df.map将隐式转换为Dataset

ds1.map(ele=>(ele))//ele类型为String
ds2.map(ele=>(ele._1,ele._2,ele._3))//ele类型为tuple

Dataframe行类型为Row,如果想获取具体字段值,必须调用Row的get()或get类型()方法

Datset行类型可以为String,可以为tuple等等,获取值像RDD那样

RDD,Dataset,Dataframe互相转换

RDD转别的

val rdd=spark.sparkContext.textFile("C:\\zlq\\data\\people.txt")

val rdd1=rdd.map(ele=>(ele.split(",")(0),ele.split(",")(1).trim.toInt))
rdd1.toDF("name","age")//转df,指定字段名
rdd1.toDS()//转ds

case class Person(name:String,age:Int)
val rdd2=rdd.map(_.split(","))
.map(ele=>(Person(ele(0),ele(1).trim.toInt))).toDF()//将自定义类转df

val schemaString="name age"
val fields=schemaString.split(" ")
    .map(ele=>StructField(ele,StringType,nullable = true))
val schema=StructType(fields)
val rdd3=rdd.map(_.split(",")).map(ele=>Row(ele(0),ele(1).trim))
val df=spark.createDataFrame(rdd3,schema)//将StructType作用到rdd上,转df

Dataframe转别的

val df=spark.sql("select date,status,api from data.api")

df.rdd
//df转ds就太多了,先列举几个
df.as() map filter flatMap等等吧

Dataset转别的

ds.rdd
//ds转df也不少,先列举
select join agg toDF()

Dataset&Dataframe算子

show()

show()//默认显示20行,字段值超过20,默认截断
show(numRows: Int)//指定显示行数
show(truncate: Boolean)//指定是否截断超过20的字符
show(numRows: Int, truncate: Boolean)//指定行数,和是否截断
show(numRows: Int, truncate: Int)//指定行数,和截断的字符长度

na()    返回包含null值的行

val df=spark.read.json("C:\\zlq\\data\\people.json")
df.show()
df.na.drop().show()

 

stat()

//{"name":"Michael"}
//{"name":"Andy", "age":30}
//{"name":"Justin", "age":19}
//{"name":"Tom", "age":19}
//{"name":"jerry", "age":19}
df.stat.freqItems(Seq("age")).show()

结果如下,你把json的后两条去掉也是这结果,会自动去重

sortWithinPartitions()

类似hive的sort by,只在分区内排序,默认降序

spark.sql(
  """
    |select distinct to_date(date) y
    |from data.api_orc
  """.stripMargin).repartition(20).sortWithinPartitions("y")
  //为了查看每个分区的数据,转成rdd,调用mapPartitionsWithIndex()
  .rdd.mapPartitionsWithIndex((x,iter)=>{
      var result=List[String]()
      for(i<-iter){
        result ::=(x+"-"+i.getDate(0))
      }
  result.toIterator
}).foreach(println)

sort()&order by()

全局排序,按指定列

spark.sql(
  """
    |select distinct to_date(date) y
    |from data.api_orc
  """.stripMargin).sort("y").show()

hint()

df1.join(df2.hint("broadcast"))//将df2广播

selectExpr()

spark.sql(
  """
    |select distinct to_date(date) y
    |from data.api_orc
  """.stripMargin).sort("y").selectExpr("y as hahha").printSchema()

filter&where

where调用的是filter

peopleDs.where("age > 15")
peopleDs.filter($"age" > 15)

groupBy&rollup&cube

返回Dataset

 ds.groupBy($"department").avg()//按部门计算平均值
 
  ds.groupBy($"department", $"gender").agg(Map(
     "salary" -> "avg",
     "age" -> "max"
   ))//计算平均工资,和最大年龄

reduce

调的就是rdd的reduce方法,传的方法返回什么类型,reduce就返回什么类型

val df=spark.read.json("C:\\zlq\\data\\people.json")
println(df.select("age").na.drop().reduce((row1, row2) => {
  Row(row1.getLong(0) + row2.getLong(0))
}).get(0))
//计算年龄总和

groupByKey()

接收一个将Row转为别的类型的函数

val df=spark.sql(
  """
    |select size,status
    |from data.api_orc
    |where to_date(date)="2019-03-18"
  """.stripMargin).groupByKey(row=>(row.getLong(1)))//取第二个字段

agg()

是ds.groupBy().agg的缩写,返回 DataFrame

spark.sql(
  """
    |select size,status
    |from data.api
    |where to_date(date)="2019-03-15"
  """.stripMargin).agg(Map("size"->"max","status"->"avg")).show()

limit(n:Int)

返回新的Dataset

union

并集,字段数必须必须相同

val df1=spark.read.json("C:\\zlq\\data\\people.json")
val df2=spark.read.json("C:\\zlq\\data\\people.json")
df1.union(df2).show()

intersect()

交集

except()

差集

df1.except(df2)//df1里有的而df2里没有的

sample()

返回Dataset,参数依次为,是否放回,抽取比例,随机种子

sample(withReplacement: Boolean, fraction: Double, seed: Long)
sample(withReplacement: Boolean, fraction: Double)

randomSplit()

将Dataset按比例大致分为结果Dataset,返回Array[Dataset]or list

randomSplit(weights: Array[Double], seed: Long)
randomSplitAsList(weights: Array[Double], seed: Long)
randomSplit(weights: Array[Double])


println(df1.collect().length)
df1.randomSplit(Array(0.3,0.4,0.3)).foreach(ele=>{
  println(ele.collect().length)
})
//结果为 29 8 13 8

flatMap&explode

返回DataFrame

println(df2.collect().length)
println(df2.flatMap(ele=>(ele.getString(1).split(","))).collect().length)
//第二个数比第一个数大,一行拆多行,行转列

withColumn

添加列或者替换列

val df=spark.createDataset(Seq(("tom",21,17),("jerry",31,19)))
   .toDF("name","age","salary")
 df.show()
 df.withColumn("rate",df("salary")/df("age")).show()
 df.withColumn("age",df("salary")).show()

 

 

 withColumnRenamed

给字段重命名

val df=spark.createDataset(Seq(("tom",21,17),("jerry",31,19)))
   .toDF("name","age","salary")
 df.withColumnRenamed("name","hah").printSchema()

drop

删除一列或者多列

val df=spark.createDataset(Seq(("tom",21,17),("jerry",31,19)))
   .toDF("name","age","salary")
 df.drop("name","age").printSchema()

dropDuplicates()

val df=spark.createDataset(Seq(("tom",21,19),("jerry",31,19),("jerry",32,18)))
   .toDF("name","age","salary")
 df.dropDuplicates("name").show()
 df.dropDuplicates("salary").show()
 df.dropDuplicates("salary","name").show()

 

 

 

describe(cols: String*): DataFrame

计算数量,均值等

val df=spark.createDataset(Seq(("tom",21,19),("jerry",31,19),("jerry",32,18)))
   .toDF("name","age","salary")
   df.describe("age","salary").show()

 

head(n: Int): Array[T]&head()&first()&take()&takeAsList

head(),first返回第一个元素,head(n)返回数组

val df=spark.createDataset(Seq(("tom",21,19),("jerry",31,19),("jerry",32,18)))
   .toDF("name","age","salary")
   for(i<-df.head(2)){
  println(i)
}
 println(df.head())
 println(df.first())

map&mapPartitions

fun(ele) fun(partition)

collect()&collectAsList()&toLocalIterator()

一个返回Array,一个返回List

count()

返回行数

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark SQL中的DataFrameDataset是两种非常重要的数据结构,它们都是基于RDD的分布式数据集,但是它们提供了更高级别的API,可以更方便地进行数据处理和分析。 DataFrame是一种类似于关系型数据库中表的数据结构,它由一组有命名的列组成,每个列都有一个数据类型。DataFrame可以通过SQL语句或者DataFrame API进行查询和操作,支持类似于SQL的聚合、过滤、排序等操作,同时也支持复杂的数据类型和嵌套结构。 DatasetSpark 1.6版本引入的新概念,它是一个类型安全的分布式数据集,可以通过编译时检查来避免类型错误。Dataset可以看作是DataFrame的扩展,它支持更多的操作和更高级别的API,同时也提供了更好的性能和可维护性。 总的来说,DataFrameDataset都是Spark SQL中非常重要的数据结构,它们提供了更高级别的API和更好的性能,可以帮助我们更方便地进行数据处理和分析。 ### 回答2: DataFrameDataSetSpark SQL中处理数据的两种最常用的API。在这两个API中,数据使用的是表格形式,而且API的使用非常类似。然而,在很多情况下,DataFrameDataSet还是有些不同的。 DataFrameSpark SQL中的一个关系数据,可以从各种数据源中读取数据,例如:结构化数据文件、Hive中的表、外部关系数据库中的表、Avro文件等等。DataFrame是基于分布式数据集的一组数据结构,每个数据集都分为行和列,并且有一个命名的列。DataFrameSpark SQL中作为一种概念,表示分布式的数据集,就像一个表格一样,它具有由向量组成的列,每一列都有一个名称和数据类型。 DataSetSpark 1.6中引入并在Spark 2.0中得到加强。DataSet是强类型API,它提供了类似于RDD的泛型编程接口,同时也继承了DataFrame的一些理念。与DataFrame不同的是,DataSet具有额外的类型安全和更好的性能。其中,DataSet是有类型的,也就是说,在DataSet中存储的数据必须要指定一个类,使用该类的实例来表示数据。 在使用的过程中,DataFrameDataSet的区别表现在: 1. 类型:DataFrame是一组分布式数据集合,是无类型的 (untyped),因为它们只是在特定的列名和数据类型上进行了验证。而DataSet是强类型的 (typed),因为DataSet可以在编译时对数据的类型进行验证。 2. 优化:DataFrame提供了基于第一代Tungsten的基于列的计算引擎来优化计算,以支持高性能计算。而DataSet提供了基于第二代Tungsten的代码生成器,产生了比DataFrame更优化的代码。 3. 开发复杂度:代码开发的复杂度上,DataSet需要在类型定义中显式声明模式 (schemas),这会增加一些重复的代码,而DataFrame不需要这样做。 在实际使用过程中,一般情况下,若处理数据时进行数值处理、聚合操作或者切片取部分数据,可以使用 DataFrame。而当数据需要更多的定制操作、需要常规编程的工作时,就要使用 DataSet。 因此,对于数据的处理操作而言,DataFrameDataSet都是非常重要的API,我们可以根据具体的业务需求来选择使用哪一种API。在使用这两个API时我们要根据自己的需求选择哪一种更适合自己的场景。 ### 回答3: Spark是当前最流行的大数据处理框架之一,它有着强大的处理能力和高效的分布式计算能力。在 Spark 中,DataFrameDataSet 是两种常用的数据结构,它们提供了很多操作特性,使 Spark SQL 变得更加方便、快捷和高效。 DataFrame 是一种有结构的分布式数据集合,它是以列为中心的数据结构,具有传统上的行和列的属性。DataFrame 是使用 Spark SQL 系统中非常重要的概念,主要用于处理结构化数据。DataFrame 支持多种数据源:csv 文件、JSON、Hive、ORC、Parquet、Apache Hive 和 JDBC 数据库等。另外,DataFrame 比 RDD 操作更加高效,在实现上采用了更高级的方法,例如使用 Catalyst 引擎进行优化和查询计划处理,同时还支持 SQL 操作。 DataSetSpark 2.0 版本新增的数据结构,它是一个类型化的分布式数据集合,与 RDD 不同,它需要在编译期间就确定类型。DataSet 数据集合支持 Scala 和 Java 两种语言,并兼容 Spark 原有的操作特性,例如分布式处理、错误容错、高效计算等操作。DataSet 在类型安全和语言特性的支持上比 DataFrame 更加强大,因此可以避免在运行时出现类型匹配错误的问题。 与 DataFrame 相比,DataSet 具有更强的类型安全性和启发式优化特性,因此在某些情况下会比 DataFrame 更加高效和快速。但是,DataSet 操作有时会变得比较复杂,并且需要程序员具备额外的类型知识。因此,根据实际需求来选择适当的数据集合是非常重要的。 总的来说,DataFrameDataSet 都是很重要的 Spark SQL 数据结构,在 Spark 编程中都有着不可替代的作用。使用 DataFrameDataSet 可以帮助我们更加快速、方便地处理分布式数据,提高我们的开发效率和代码质量。建议根据项目的需要来选择使用哪种数据集合,在具体操作中尽量避免数据类型转换和类型匹配错误等问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值