2016-05-03 63 views
7

Spark documentation显示了如何使用Scala案例类来推断架构,从RDD创建DataFrame。我试图用sqlContext.createDataFrame(RDD, CaseClass)来重现这个概念,但是我的DataFrame结果是空的。这里是我的Scala代码:如何将基于案例类的RDD转换为DataFrame?

// sc is the SparkContext, while sqlContext is the SQLContext. 

// Define the case class and raw data 
case class Dog(name: String) 
val data = Array(
    Dog("Rex"), 
    Dog("Fido") 
) 

// Create an RDD from the raw data 
val dogRDD = sc.parallelize(data) 

// Print the RDD for debugging (this works, shows 2 dogs) 
dogRDD.collect().foreach(println) 

// Create a DataFrame from the RDD 
val dogDF = sqlContext.createDataFrame(dogRDD, classOf[Dog]) 

// Print the DataFrame for debugging (this fails, shows 0 dogs) 
dogDF.show() 

我看到的输出是:

Dog(Rex) 
Dog(Fido) 
++ 
|| 
++ 
|| 
|| 
++ 

我缺少什么?

谢谢!

回答

12

所有你需要的仅仅是

val dogDF = sqlContext.createDataFrame(dogRDD) 

第二个参数是Java的API的一部分,并希望你的类遵循Java Bean约定(getter/setter方法)。您的案例类不遵循此约定,因此没有检测到属性,导致没有列的空DataFrame。

+1

这个工作。我还必须将case类的定义移到主函数之外,以避免出现'error:No TypeTag for Dog''。谢谢! – sparkour

+0

我明白了,非常有趣,所以第二个参数只有在从Java API调用时才需要,scala会自动检测应该转换为列的Type字段? – qwwqwwq

5

您可以使用toDF如下例类实例的Seq直接创建DataFrame

val dogDf = Seq(Dog("Rex"), Dog("Fido")).toDF 
0

案例类方法不能在集群模式下运行。它会给你定义的案例类别ClassNotFoundException

转换它RDD[Row]StructField定义RDD的架构,然后createDataFrame

val rdd = data.map { attrs => Row(attrs(0),attrs(1)) } 

val rddStruct = new StructType(Array(StructField("id", StringType, nullable = true),StructField("pos", StringType, nullable = true))) 

sqlContext.createDataFrame(rdd,rddStruct) 

toDF()不会工作要么

相关问题