【大数据学习】SparkSQL之 DataFrame与RDD的互操作

根据官网介绍:Spark SQL支持两种不同的方法将现有的RDDs转换为数据集。第一种方使用反射来推断包含特定对象类型的RDD的模式。这种基于反射的方法可以生成更简洁的代码,并且当您在编写Spark应用程序时已经知道模式时,这种方法可以很好地工作。这种方式虽然简单,但是不通用;因为生产中的字段是非常非常多的。创建数据集的第二种方法是通过编程接口,该接口允许您构造模式,然后将其应用于现有的RDD。虽然这个方法更详细,但它允许您在列及其类型直到运行时才知道时构造数据集。为什么要转成RDD呢,因为我们大部分的数据都在HDFS上的。

下面用例子来说明两种用法:

object DFApp {

  def main(args: Array[String]): Unit = {

    val sparkSession= SparkSession.builder()

      .appName("DFApp")

      .master("local[2]")

      .getOrCreate()

    inferReflection(sparkSession)

    //    val lines=sc.textFile("file:///E:/data.txt")

    sparkSession.stop()

  }


  /**********************************DataFrame和RDD的互操作  反射的方式 *******************************/

  def inferReflection(sparkSession: SparkSession): Unit ={
    val info=sparkSession.sparkContext.textFile("file:///E:/data.txt")

    //****用反射的方式将RDD转换成DataFrame需要导入隐式转换。import 后面的名字不是固定的,而是sparksession的名字,因为前面创建的sparksession叫做sparkSession,所以就用sparkSession.implcits._  ****//

    import sparkSession.implicits._

    val df=info.map(_.split("\t")).map(x=>Info(x(0),x(1),x(2).toLong)).toDF()

    df.show()


    //基于DataFrame的API编程
    df.groupBy("domain").sum("responseSize").show()

    //基于sql API编程,把DataFrame注册成一张临时表,表名info
    df.createOrReplaceTempView("info")
    sparkSession.sql("select domain,sum(responseSize) from info group by domain").show()

  }

  //注意:用反射的方式把RDD转DataFrame需要用到case class,case class 需要建在main方法以外,否则会报错
  case class Info(ip:String,domain:String,responseSize:Long)

}
show()的输出结果:

 

上面的例子是用第一个方法实现的,但是不建议使用,因为在工作当中,使用这种方式是有限制的。 对于以前的版本来说,case class最多支持22个字段如果超过了22个字段,我们就必须要自己开发一个类,实现product接口才行。因此这种方式虽然简单,但是不通用;因为生产中的字段是非常非常多的,是不可能只有20来个字段的。 

下面介绍第二个方法

以编程的方式指定DataFrame,这种方式用得非常多。通过编程方式指定schema ,对于第一种方式的schema其实定义在了case class里面了。 

官网解读:如果不能提前定义case(例如,记录的结构编码在字符串中,或者文本数据集将被解析,字段将针对不同的用户以不同的方式投影),因为在实际业务处理中,你的字段可能在变化,因此很难去提前定义,这时则可以通过三个步骤以编程方式创建数据DataFrame

  1. Create an RDD of Rows from the original RDD;

           从原始RDD创建行RDD

      2.Create the schema represented by a StructType matching the structure of Rows in the RDD created in Step 1.

          创建由StructType表示的模式,该结构类型与步骤1中创建的RDD中的行结构匹配

      3.Apply the schema to the RDD of Rows via createDataFrame method provided by SparkSession.

         通过SparkSession提供的createDataFrame方法将模式应用于行RDD

object DFApp {
  def main(args: Array[String]): Unit = {
    val sparkSession= SparkSession.builder()
      .appName("DFApp")
      .master("local[2]")
      .getOrCreate()

    inferReflection(sparkSession)
    //    val lines=sc.textFile("file:///E:/data.txt")

    programmatically(sparkSession)
    sparkSession.stop()
  }

/************************************DataFrarm和RDD的互操作   编程的方式*******************************/
def  programmatically(sparkSession: SparkSession): Unit ={
  val info=sparkSession.sparkContext.textFile("file:///E:/data.txt")

  import sparkSession.implicits._

  //1 Create an RDD of Rows from the original RDD,即从原始的RDD创建一个Rows类型的RDD
  val rdd=info.map(_.split("\t")).map(x=>Row(x(0),x(1),x(2).toLong))

  //2.定义schema,使用structType来指定
  val struct= types.StructType(
    Array(
    StructField("ip", StringType, true),
    StructField("domain", StringType, false),
    StructField("responseSize", LongType, false)
    )
  )

  // 3.把这个schema作用到RDD的Rows上。通过sparkSession.createDataFrame方法
  val df=sparkSession.createDataFrame(rdd,struct)
  df.show()
}

 

运行后同样可以得到结果

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值