Dataframe Spark中数据帧、数据集和RDD之间的差异

Dataframe Spark中数据帧、数据集和RDD之间的差异,dataframe,apache-spark,apache-spark-sql,rdd,apache-spark-dataset,Dataframe,Apache Spark,Apache Spark Sql,Rdd,Apache Spark Dataset,我只是想知道Apache Spark中的RDD和DataFrame(Spark 2.0.0 DataFrame只是Dataset[Row]的类型别名)之间有什么区别 你能把一个转换成另一个吗?ADataFrame通过谷歌搜索“DataFrame definition”定义得很好: 数据帧是一个表或二维数组状结构 每列包含一个变量的测量值,每行 包含一个案例 因此,DataFrame由于其表格格式,具有额外的元数据,这允许Spark对最终确定的查询运行某些优化 另一方面,RDD,仅仅是一个Resl

我只是想知道Apache Spark中的
RDD
DataFrame
(Spark 2.0.0 DataFrame只是
Dataset[Row]
的类型别名)之间有什么区别


你能把一个转换成另一个吗?

A
DataFrame
通过谷歌搜索“DataFrame definition”定义得很好:

数据帧是一个表或二维数组状结构 每列包含一个变量的测量值,每行 包含一个案例

因此,
DataFrame
由于其表格格式,具有额外的元数据,这允许Spark对最终确定的查询运行某些优化

另一方面,
RDD
,仅仅是一个ReslientD分布的D数据集,它更像是一个无法优化的数据黑盒,因为可以对其执行的操作没有那么受约束

但是,您可以通过其
RDD
方法从数据帧转到
RDD
,也可以通过
toDF
方法从
RDD
转到
DataFrame
(如果RDD是表格格式)


一般而言由于内置查询优化,建议尽可能使用
数据框

数据框相当于RDBMS中的表,也可以类似于RDDs中的“本机”分布式集合的方式进行操作。与RDD不同,数据帧跟踪模式并支持各种关系操作,从而实现更优化的执行。
每个DataFrame对象表示一个逻辑计划,但由于其“惰性”性质,在用户调用特定的“输出操作”之前不会执行任何操作。

简单地说,
RDD
是核心组件,而
DataFrame
是spark 1.30中引入的API

RDD 名为
RDD
的数据分区集合。这些
RDD
必须遵循以下几个属性:

  • 一成不变
  • 容错
  • 分发
  • 更多
在这里,
RDD
可以是结构化的,也可以是非结构化的

数据帧
DataFrame
是Scala、Java、Python和R中可用的API。它允许处理任何类型的结构化和半结构化数据。要定义
DataFrame
,将分布式数据集合组织到名为
DataFrame
的命名列中。您可以在
DataFrame
中轻松优化
rdd
。 您可以使用
DataFrame
一次处理JSON数据、拼花地板数据和HiveQL数据

val sampleRDD = sqlContext.jsonFile("hdfs://localhost:9000/jsondata.json")

val sample_DF = sampleRDD.toDF()

这里SAMPAREDF考虑为<代码>数据文件< /代码>。code>sampleRDD被称为

RDD

,因为
DataFrame
是弱类型的,开发人员无法从类型系统中获益。例如,假设您想从SQL中读取一些内容并在其上运行一些聚合:

val people = sqlContext.read.parquet("...")
val department = sqlContext.read.parquet("...")

people.filter("age > 30")
  .join(department, people("deptId") === department("id"))
  .groupBy(department("name"), "gender")
  .agg(avg(people("salary")), max(people("age")))
当你说
people(“deptId”)
时,你没有得到一个
Int
,或者一个
Long
,你得到的是一个需要操作的
对象。在具有丰富类型系统(如Scala)的语言中,最终会丢失所有类型安全性,这会增加编译时可能发现的运行时错误的数量

相反,
DataSet[T]
是类型化的。当您这样做时:

val people: People = val people = sqlContext.read.parquet("...").as[People]
实际上,您将返回一个
People
对象,其中
deptId
是一个实际的整数类型,而不是列类型,因此利用了类型系统

从Spark 2.0开始,DataFrame和DataSet API将统一,其中,
DataFrame
将是
DataSet[Row]
的类型别名

首先,
DataFrame
是从
SchemaRDD
演变而来的

是的。。
Dataframe
RDD
之间的转换是完全可能的

下面是一些示例代码片段

  • df.rdd
    is
    rdd[Row]
下面是创建dataframe的一些选项

  • 1)
    yourrddOffrow.toDF
    转换为
    DataFrame

  • val sampleRDD = sqlContext.jsonFile("hdfs://localhost:9000/jsondata.json")
    
    val sample_DF = sampleRDD.toDF()
    
  • 2) 使用sql上下文的
    createDataFrame

    val df=spark.createDataFrame(rddOfRow,schema)

其中模式可以来自以下一些选项
来自scala案例类和scala反射api

import org.apache.spark.sql.catalyst.ScalaReflection
val schema = ScalaReflection.schemaFor[YourScalacaseClass].dataType.asInstanceOf[StructType]
或使用
编码器

import org.apache.spark.sql.Encoders
val mySchema = Encoders.product[MyCaseClass].schema
如模式所述,还可以使用
StructType
StructField

val schema = new StructType()
  .add(StructField("id", StringType, true))
  .add(StructField("col1", DoubleType, true))
  .add(StructField("col2", DoubleType, true)) etc...

  • RDD
    API:
  • RDD
    (弹性分布式数据集)API自发布以来一直处于活跃状态 1.0版本

    RDD
    API提供了许多转换方法,例如
    map
    (),
    filter
    ()和
    reduce
    ()用于对数据执行计算。每个 在这些方法中,有一个新的
    RDD
    表示转换后的 数据。但是,这些方法只是定义要执行的操作 已执行,并且在执行操作之前不会执行转换 方法被调用。动作方法的示例有
    收集
    ()和
    
    saveAsObjectFile
    ()

    RDD示例:

    rdd.filter(_.age > 21) // transformation
       .map(_.last)// transformation
    .saveAsObjectFile("under21.bin") // action
    
    dataset.filter(_.age < 21);
    
    示例:使用RDD按属性筛选

    rdd.filter(_.age > 21)
    
  • DataFrame
    API
  • Spark 1.3作为项目的一部分,引入了一个新的
    DataFrame
    API 钨倡议,旨在提高性能和 Spark的可伸缩性。
    DataFrame
    API引入了 模式来描述数据,允许Spark管理模式和 只在节点之间传递数据,比使用 Java序列化

    DataFrame
    API与
    RDD
    API完全不同,因为它 是A吗
    case class Person(name : String , age : Int) 
    val dataframe = sqlContext.read.json("people.json") 
    dataframe.filter("salary > 10000").show 
    => throws Exception : cannot resolve 'salary' given input age , name
    
    case class Person(name : String , age : Int)
    val personRDD = sc.makeRDD(Seq(Person("A",10),Person("B",20)))
    val personDF = sqlContext.createDataframe(personRDD)
    personDF.rdd // returns RDD[Row] , does not returns RDD[Person]
    
    case class Person(name : String , age : Int)
    val personRDD = sc.makeRDD(Seq(Person("A",10),Person("B",20)))
    val personDF = sqlContext.createDataframe(personRDD)
    val ds:Dataset[Person] = personDF.as[Person]
    ds.filter(p => p.age > 25)
    ds.filter(p => p.salary > 25)
     // error : value salary is not a member of person
    ds.rdd // returns RDD[Person]
    
    ds.select(col("name").as[String], $"age".as[Int]).collect()
    
    val rowsRdd: RDD[Row] = sc.parallelize(
      Seq(
        Row("first", 2.0, 7.0),
        Row("second", 3.5, 2.5),
        Row("third", 7.0, 5.9)
      )
    )
    
    val df = spark.createDataFrame(rowsRdd).toDF("id", "val1", "val2")
    
    df.show()
    +------+----+----+
    |    id|val1|val2|
    +------+----+----+
    | first| 2.0| 7.0|
    |second| 3.5| 2.5|
    | third| 7.0| 5.9|
    +------+----+----+
    
    val rowsRdd: RDD[Row] = df.rdd() // DataFrame to RDD