64、Spark SQL之使用编程方式将RDD转换为DataFrame

使用编程方式指定元数据

Java版本:当JavaBean无法预先定义和知道的时候,比如要动态从一个文件中读取数据结构,那么就只能用编程方式动态指定元数据了。首先要从原始RDD创建一个元素为Row的RDD;其次要创建一个StructType,来代表Row;最后将动态定义的元数据应用到RDD<Row>上。
Scala版本:Scala的实现方式,与Java是基本一样的。
Java版本

public class RDD2DataFrameProgrammatically {

    public static void main(String[] args) {
        // 创建SparkConf、JavaSparkContext、SQLContext
        SparkConf conf = new SparkConf().setAppName("RDD2DataFrameProgrammaticallyJava").setMaster("local");
        JavaSparkContext sparkContext = new JavaSparkContext(conf);

        SQLContext sqlContext = new SQLContext(sparkContext);

        // 第一步,创建一个普通的RDD,但是,必须将其转换为RDD<Row>的这种格式
        JavaRDD<String> lines = sparkContext.textFile("E:\\testdata\\sparksql\\students.txt");

        // 往Row中塞数据的时候,要注意,什么格式的数据,就用什么格式转换一下,再塞进去
        JavaRDD<Row> studentRDD = lines.map(new Function<String, Row>() {
            @Override
            public Row call(String s) throws Exception {
                String[] strings = s.split(",");
                return RowFactory.create(Integer.parseInt(strings[0]),
                        strings[1],
                        Integer.parseInt(strings[2]));
            }
        });

        // 第二步,动态构造元数据
        // 比如说,id、name等,field的名称和类型,可能都是在程序运行过程中,动态从mysql db里
        // 或者是配置文件中,加载出来的,是不固定的
        // 所以特别适合用这种编程的方式,来构造元数据
        List<StructField> fieldList = new ArrayList<StructField>();
        fieldList.add(DataTypes.createStructField("id",DataTypes.IntegerType, true));
        fieldList.add(DataTypes.createStructField("name",DataTypes.StringType, true));
        fieldList.add(DataTypes.createStructField("age",DataTypes.IntegerType, true));
        StructType structType = DataTypes.createStructType(fieldList);

        // 第三步,使用动态构造的元数据,将RDD转换为DataFrame
        DataFrame df = sqlContext.createDataFrame(studentRDD, structType);

        // 前面讲的DataFrame的常用操作依然试用
        df.show();
        df.schema();

        df.select(df.col("id")).show();
        df.select(df.col("name")).show();
        df.select(df.col("age")).show();
        df.select(df.col("id"), df.col("name"), df.col("age").plus(1));
        df.filter(df.col("age").gt(18)).show();
        df.groupBy(df.col("age")).count().show();

        df.registerTempTable("students");

        DataFrame teenagerDF = sqlContext.sql("select * from students where age < 18");

        teenagerDF.show();

        List<Row> collect = teenagerDF.javaRDD().collect();
        for(Row row : collect) {
            System.out.println(row.getInt(0) + "," + row.getString(1) + "," + row.getInt(2));
        }
    }
}

Scala版本

object RDD2DataFrameProgrammatically {

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("RDD2DataFrameProgrammaticallyScala")
    val sparkContext = new SparkContext(conf)
    val sqlContext = new SQLContext(sparkContext)

    // 第一步,构造出元素为Row的普通RDD
    val lines = sparkContext.textFile("E:\\testdata\\sparksql\\students.txt")
    val students = lines.map(line => {
      val strings = line.split(",")
      Row(strings(0).toInt, strings(1), strings(2).toInt)
    })
    // 第二步,编程方式动态构造元数据
    val structType = StructType(Array(
      StructField("id", DataTypes.IntegerType, true),
      StructField("name", DataTypes.StringType, true),
      StructField("age", DataTypes.IntegerType, true)
    ))

    // 第三步,进行RDD到DataFrame的转换
    val df = sqlContext.createDataFrame(students, structType)

    // 前面讲的DataFrame的常用操作依然试用
    df.show()
    df.schema
    df.select(df.col("id")).show()
    df.select(df.col("name")).show()
    df.select(df.col("age")).show()
    df.select(df.col("id"), df.col("name"), df.col("age").plus(1))
    df.filter(df.col("age").gt(18)).show()
    df.groupBy(df.col("age")).count().show()

    df.registerTempTable("students")
    val teenagerDF = sqlContext.sql("select * from students where age < 18")
    teenagerDF.show()
    val rows = teenagerDF.rdd.collect()
    for(row <- rows){
      println(row.getAs("id").toString + "," + row.getAs("name").toString + "," + row.getAs("age").toString)
    }
    teenagerDF.rdd.foreach(row => println(row))
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值