Spark SQL有两种方法将RDD转为DataFrame。

1. 使用反射机制,推导包含指定类型对象RDD的schema。这种基于反射机制的方法使代码更简洁,而且如果你事先知道数据schema,推荐使用这种方式;

2. 编程方式构建一个schema,然后应用到指定RDD上。这种方式更啰嗦,但如果你事先不知道数据有哪些字段,或者数据schema是运行时读取进来的,那么你很可能需要用这种方式。

利用反射推导schema

Spark SQL的Scala接口支持自动将包含case class对象的RDD转为DataFrame。对应的case class定义了表的schema。case class的参数名通过反射,映射为表的字段名。case class还可以嵌套一些复杂类型,如Seq和Array。RDD隐式转换成DataFrame后,可以进一步注册成表。随后,你就可以对表中数据使用SQL语句查询了。

// sc 是已有的 SparkContext 对象
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
// 为了支持RDD到DataFrame的隐式转换
import sqlContext.implicits._ // 定义一个case class.
// 注意:Scala 2.10的case class最多支持22个字段,要绕过这一限制,
// 你可以使用自定义class,并实现Product接口。当然,你也可以改用编程方式定义schema
case class Person(name: String, age: Int) // 创建一个包含Person对象的RDD,并将其注册成table
val people = sc.textFile("examples/src/main/resources/people.txt").map(_.split(",")).map(p => Person(p(0), p(1).trim.toInt)).toDF()
people.registerTempTable("people") // sqlContext.sql方法可以直接执行SQL语句
val teenagers = sqlContext.sql("SELECT name, age FROM people WHERE age >= 13 AND age <= 19") // SQL查询的返回结果是一个DataFrame,且能够支持所有常见的RDD算子
// 查询结果中每行的字段可以按字段索引访问:
teenagers.map(t => "Name: " + t(0)).collect().foreach(println) // 或者按字段名访问:
teenagers.map(t => "Name: " + t.getAs[String]("name")).collect().foreach(println) // row.getValuesMap[T] 会一次性返回多列,并以Map[String, T]为返回结果类型
teenagers.map(_.getValuesMap[Any](List("name", "age"))).collect().foreach(println)
// 返回结果: Map("name" -> "Justin", "age" -> 19)

编程方式定义Schema

如果不能事先通过case class定义schema(例如,记录的字段结构是保存在一个字符串,或者其他文本数据集中,需要先解析,又或者字段对不同用户有所不同),那么你可能需要按以下三个步骤,以编程方式的创建一个DataFrame:

  1. 从已有的RDD创建一个包含Row对象的RDD
  2. 用StructType创建一个schema,和步骤1中创建的RDD的结构相匹配
  3. 把得到的schema应用于包含Row对象的RDD,调用这个方法来实现这一步:SQLContext.createDataFrame

For example:

例如:

// sc 是已有的SparkContext对象
val sqlContext = new org.apache.spark.sql.SQLContext(sc) // 创建一个RDD
val people = sc.textFile("examples/src/main/resources/people.txt") // 数据的schema被编码与一个字符串中
val schemaString = "name age" // Import Row.
import org.apache.spark.sql.Row; // Import Spark SQL 各个数据类型
import org.apache.spark.sql.types.{StructType,StructField,StringType}; // 基于前面的字符串生成schema
val schema =
StructType(
schemaString.split(" ").map(fieldName => StructField(fieldName, StringType, true))) // 将RDD[people]的各个记录转换为Rows,即:得到一个包含Row对象的RDD
val rowRDD = people.map(_.split(",")).map(p => Row(p(0), p(1).trim)) // 将schema应用到包含Row对象的RDD上,得到一个DataFrame
val peopleDataFrame = sqlContext.createDataFrame(rowRDD, schema) // 将DataFrame注册为table
peopleDataFrame.registerTempTable("people") // 执行SQL语句
val results = sqlContext.sql("SELECT name FROM people") // SQL查询的结果是DataFrame,且能够支持所有常见的RDD算子
// 并且其字段可以以索引访问,也可以用字段名访问
results.map(t => "Name: " + t(0)).collect().foreach(println)

RDD转换DataFrame的更多相关文章

  1. RDD与DataFrame的转换

    RDD与DataFrame转换1. 通过反射的方式来推断RDD元素中的元数据.因为RDD本身一条数据本身是没有元数据的,例如Person,而Person有name,id等,而record是不知道这些的 ...

  2. spark-DataFrame之RDD和DataFrame之间的转换

    package cn.spark.study.core.mycode_dataFrame; import java.io.Serializable;import java.util.List; imp ...

  3. 045 RDD与DataFrame互相转换

    一:RDD与DataFrame互相转换 1.总纲 二:DataFrame转换为RDD 1.rdd 使用schema可以获取DataFrame的schema 使用rdd可以获取DataFrame的数据 ...

  4. RDD、DataFrame、Dataset三者三者之间转换

    转化: RDD.DataFrame.Dataset三者有许多共性,有各自适用的场景常常需要在三者之间转换 DataFrame/Dataset转RDD: 这个转换很简单 val rdd1=testDF. ...

  5. Spark之 RDD转换成DataFrame的Scala实现

    依赖 <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2. ...

  6. 转】RDD与DataFrame的转换

    原博文出自于: http://www.cnblogs.com/namhwik/p/5967910.html RDD与DataFrame转换1. 通过反射的方式来推断RDD元素中的元数据.因为RDD本身 ...

  7. sparksql 用反射的方式将rdd转换成dataset/dataframe

    java public class ReflectionDemo { private static SparkConf conf = new SparkConf().setAppName(" ...

  8. RDD转换成为DataFrame

    方式一: 通过case class创建DataFrames(反射) TestDataFrame1.scala package com.bky // 隐式类的导入 // 定义case class,相当于 ...

  9. RDD、DataFrame和DataSet的区别

    原文链接:http://www.jianshu.com/p/c0181667daa0 RDD.DataFrame和DataSet是容易产生混淆的概念,必须对其相互之间对比,才可以知道其中异同. RDD ...

随机推荐

  1. html增加和删除div

    <!DOCTYPE HHTML"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> ...

  2. javascript转换时间戳

    var unixTimestamp = new Date(1513814400000);commonTime = unixTimestamp.toLocaleString();

  3. Mysql Left Join Where On

    select t1.id,t2.idfrom t1left join t2 on t1.id = t2.id and t1.id>1 and t2.id<>3在mysql的left ...

  4. JAVA & Android 等待线程池内任务全部完成后退出

    void shutdownAndAwaitTermination(ExecutorService pool) { pool.shutdown(); // Disable new tasks from ...

  5. django生成文件txt、pdf(在生成 PDF 文件之前,需要安装 ReportLab 库)

    from django.http import HttpResponse def download_file(request): # Text file #response = HttpRespons ...

  6. CentOS 7 修改网卡名

    假设原网卡名为eth1, 那么在 /etc/sysconfig/network-scripts/ 目录下,必定会存在一个文件名为ifcfg-eth1,和网卡名对应, 这里假设要修改为eth0. 方法一 ...

  7. Log4j 把不同包的日志打印到不同位置

    如果需要将不同的日志打印到不同的地方,则需要定义不同的Appender,然后定义每一个 Appender的日志级别.打印形式.输出位置! 配置log4j.properties文件如下: ####### ...

  8. shell 脚本启动tomcat服务

    #!/bin/bash # kill tomcat进程 tomcat_fashion_dev_pid=`ps aux|grep tomcat_fashion_dev|grep -v "gre ...

  9. ios中二维码的用法

    网上的例子 zbar 下载地址 http://pan.baidu.com/share/link?shareid=2652605686&uk=9237761871.新建一个工程A:view-ba ...

  10. Mysql模糊查询 select count(*) from sys_invitation where from_id like '%1006%';

    select count(*) from sys_invitation where from_id like '%1006%'; 查询结果 select * from sys_invitation w ...