sparkSQL.createDataFrame

时间:2016-02-24 06:24:22

标签: scala apache-spark apache-spark-sql boxing

以下代码失败:

val RDD = sparkContext.parallelize(Seq(
  Row("123", new java.lang.Integer(456))
))
val schema = StructType(
  StructField("str", StringType) ::
  StructField("dbl", DoubleType) :: Nil
)
val df = sqlContext.createDataFrame(RDD, schema)
df.collect().foreach(println)

有这个例外:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
    at scala.runtime.BoxesRunTime.unboxToDouble(BoxesRunTime.java:119)
    at org.apache.spark.sql.catalyst.expressions.BaseGenericInternalRow$class.getDouble(rows.scala:44)
    at org.apache.spark.sql.catalyst.expressions.GenericInternalRow.getDouble(rows.scala:221)
    ....

请注意,这只是一个测试用例,在实际情况下,java.lang.Integer是从另一个函数返回的,因此我无法从头开始创建带有未装箱数值的Row。

如何解决这个问题?

2 个答案:

答案 0 :(得分:4)

Integer不是Double,Spark在抱怨中是正确的。 Typecast手动:

val toDouble = udf {x: Int => x.toDouble}
df.withColumn("dbl", toDouble(df.col("ints")))

答案 1 :(得分:0)

您可以在创建DataFrame之前将Ints转换为双打:

val newRdd = RDD.map({ case Row(str, i: java.lang.Integer) => Row(str, i.toDouble) })
val df = sqlContext.createDataFrame(newRdd, schema)