RDD转换成DataFrame的两种方式

一、概述

Spark SQL支持两种不同的方式将RDD转换为DataFrame。第一种是使用反射来推断包含特定类型对象的RDD的模式,这种基于反射的方式可以提供更简洁的代码,如果在编写Spark应用程序时,已经明确了schema,可以使用这种方式。第二种方式是通过可编程接口来构建schema,然后将其应用于现有的RDD。此方式编写的代码更冗长,但在不知道colum及其type的情况下,可以使用这种方式。

下面案例的数据集如下people.txt:

Michael, 29
Andy, 30 
Justin, 19

二、RDD转DataFrame案例

    1.通过反射的方式

          Spark SQL的Scala接口支持自动将包含样例类的RDD转换为DataFrame。样例类定义表的schema。通过反射读取样例类的参数名称,并映射成column的名称。

package com.company.sparksql

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession

object RDD2DF_m1 {
  //创建样例类
  case class  Person(name: String, age: Int)
  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder()
      .appName("RDD2DF_m1")
      .master("local")
      .getOrCreate()
    Logger.getLogger("org.apache.spark").setLevel(Level.OFF)
    Logger.getLogger("org.apache.hadoop").setLevel(Level.OFF)
    runRDD2DF(spark)
  }

  private def runRDD2DF(spark: SparkSession) = {
    //导入隐式转换,用于RDD转为DataFrame
    import spark.implicits._
    //从文本文件中创建RDD,并将其转换为DataFrame
    val peopleDF = spark.sparkContext
      .textFile("file:///E:/people.txt")
      .map(_.split(","))
      .map(attributes => Person(attributes(0), attributes(1).trim.toInt))
      .toDF()
    //将DataFrame注册成临时视图
    peopleDF.createOrReplaceTempView("people")
    // 运行SQL语句
    val teenagersDF = spark.sql("SELECT name, age FROM people WHERE age BETWEEN 13 AND 19")
    // 使用字段索引访问列
    teenagersDF.map(teenager => "Name: " + teenager(0)).show()
    // +------------+
    // |       value|
    // +------------+
    // |Name: Justin|
    // +------------+

    // 通过字段名访问列
    teenagersDF.map(teenager => "Name: " + teenager.getAs[String]("name")).show()
    // +------------+
    // |       value|
    // +------------+
    // |Name: Justin|
    // +------------+
  }
}

  2.通过构建schema的方式

          通过构建schema的方式创建DataFrame主要包括三步:

             (1)从原始RDD创建Row类型的RDD
             (2)使用StructType,创建schema
             (3)通过createDataFrame方法将schema应用于Row类型的RDD 

package com.company.sparksql

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession}

object RDD2DF_m2 {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder()
      .appName("RDD2DF_m1")
      .master("local")
      .getOrCreate()
    Logger.getLogger("org.apache.spark").setLevel(Level.OFF)
    Logger.getLogger("org.apache.hadoop").setLevel(Level.OFF)
    runRDD2DF(spark)
  }

  private def runRDD2DF(spark: SparkSession) = {
    //导入隐式转换,用于RDD转为DataFrame
    import spark.implicits._
    //创建原始RDD
    val peopleRDD = spark.sparkContext.textFile("file:///E:/people.txt")
    //step 1 将原始RDD转换为ROW类型的RDD
    val rowRDD = peopleRDD
      .map(_.split(","))
      .map(attributes => Row(attributes(0), attributes(1).trim.toInt))
    //step 2 创建schema
    val schema = StructType(Array(
      StructField("name", StringType, true),
      StructField("age", IntegerType, true)
    ))
    //step 3 创建DF
    val peopleDF = spark.createDataFrame(rowRDD, schema)
    // 将DataFrame注册成临时视图
    peopleDF.createOrReplaceTempView("people")
    // 运行SQL语句
    val results = spark.sql("SELECT name FROM people")
    // 使用字段索引访问列
    results.map(attributes => "Name: " + attributes(0)).show()
    // +-------------+
    // |        value|
    // +-------------+
    // |Name: Michael|
    // |   Name: Andy|
    // | Name: Justin|
    // +-------------+
  }
}

       

posted @ 2018-10-31 15:11  大数据技术与数仓  阅读(1042)  评论(0编辑  收藏  举报