Apache spark 创建带有模式的数据帧时发生java.lang.ClassCastException

Apache spark 创建带有模式的数据帧时发生java.lang.ClassCastException,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,我有一些作为行值的传入数据,我必须应用特定的模式并创建一个数据帧,以下是我的代码: val rowValues=List(“12”,“F”,“1980-10-111980-10-11T10:10:20”) val rdd=sqlContext.sparkContext.parallelize(Seq(rowValues)) val rowRdd=rdd.map(v=>Row(v:*)) var fieldSchema=ListBuffer[StructField]() fieldSchema+=

我有一些作为行值的传入数据,我必须应用特定的模式并创建一个数据帧,以下是我的代码:

val rowValues=List(“12”,“F”,“1980-10-111980-10-11T10:10:20”)
val rdd=sqlContext.sparkContext.parallelize(Seq(rowValues))
val rowRdd=rdd.map(v=>Row(v:*))
var fieldSchema=ListBuffer[StructField]()
fieldSchema+=StructField(“C0”,整数类型,true,null)
fieldSchema+=StructField(“C1”,StringType,true,null)
fieldSchema+=StructField(“C2”,时间戳类型,true,null)
val schema=StructType(fieldSchema.toList)
val newRow=sqlContext.createDataFrame(rowRdd,schema)
newRow.printSchema()//此处打印新架构
newRow.show()//此操作失败,出现ClassCast异常
此操作失败,原因是
org.apache.spark.SparkException:作业因阶段失败而中止:阶段16.0中的任务0失败1次,最近的失败:阶段16.0中的任务0.0丢失(TID 16,localhost):java.lang.ClassCastxception:java.lang.String无法转换为java.sql.Timestamp


如何应用此模式?

您的输入数据都是字符串,但
c0
的模式是
integer
c1
string
c2
timestamp
,因此您会得到转换错误。您的字符串
时间戳
看起来更复杂

如果您只是想获取一个
数据帧
,那么应该将所有列
数据类型
更改为
字符串
,这样就可以了

fieldSchema += StructField("C0", StringType, true, null)
fieldSchema += StructField("C1", StringType, true, null)
fieldSchema += StructField("C2", StringType, true, null)
你应该

+---+---+------------------------------+
|C0 |C1 |C2                            |
+---+---+------------------------------+
|12 |F  |1980-10-11,1980-10-11T10:10:20|
+---+---+------------------------------+
如果您坚持使用您的模式,下面的代码应该会给出更好的想法

val rowValues = List("12","F","1980-10-11,1980-10-11T10:10:20")
val rdd = sqlContext.sparkContext.parallelize(Seq(rowValues))

val rowRdd = rdd.map(v => Row(v(0).toInt, v(1), v(2).split(",")(1).replace("T", " ")))

var fieldSchema = ListBuffer[StructField]()

fieldSchema += StructField("C0", IntegerType, true)
fieldSchema += StructField("C1", StringType, true)
fieldSchema += StructField("C2", StringType, true)
val schema = StructType(fieldSchema.toList)

val newRow = sqlContext.createDataFrame(rowRdd, schema).withColumn("C2", unix_timestamp(col("C2")))
newRow.printSchema()   // new schema prints here
newRow.show(false)
您还可以使用case类来完成此操作

import sqlContext.implicits._

def convertToDate(dateTime: String): Timestamp = {
  val formatter = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss")
  val utilDate = formatter.parse(dateTime)
  new Timestamp(utilDate.getTime)
}
val rowValues = List("12","F","1980-10-11 10:10:20")
val rdd = sqlContext.sparkContext.parallelize(Seq(rowValues))

val rowRdd = rdd.map(v => Pratap(v(0).toInt, v(1), convertToDate(v(2))))

val newRow = rowRdd.toDF
newRow.printSchema()   
newRow.show(false)
您的case类应该在主类之外

case class Pratap(C0: Int, C1: String, C2: java.sql.Timestamp)

您可以将dataframe中的列强制转换为您的模式,而不是应用模式

可以使用withColumn to with cast函数更改列的数据类型

下面是一个简单的例子

导入spark.implicits_
val df=spark.sparkContext.parallelize(Seq(
(“12”,“F”,“1980-10-11T10:10:20”),
(“12”,“F”,“1980-10-11T10:10:20”)
)).toDF(“c0”、“c1”、“c2”)
val newDf=df.withColumn(“c0”,df(“c0”).cast(整数类型))
.withColumn(“c2”,df(“c2”).cast(时间型))
//将字符串日期强制转换为时间戳
val newDf=df.withColumn(“c0”,df(“c0”).cast(整数类型))
.带列(“c2”,至utc时间戳(df(“c2”),“yyyy-MM-dd-HH:MM:ss”))
//to_utc_timestamp创建给定列和日期格式的时间戳表单
newDf.show(false)
newDf.printSchema()

希望这有帮助

谢谢你的快速回复,但我只想要这个模式-c0是整数,c1是字符串,c2是时间戳,有没有办法用这个模式创建数据帧?谢谢,我也想使用我自己的模式,上面的with column/cast对基本类型有效,但是自定义模式如何,这个模式只有在运行时才知道…|--C0:integer(nullable=true)|--C1:integer(nullable=true)|--C2:struct(nullable=true)|--Gender:string(nullable=true)更新了我的答案:如果它仍然不能回答您要查找的内容,请解释动态意味着什么Hanks,但我不能立即定义case类,因为只有在运行时才能知道模式。根据传入的模式,应该有一种方法来生成此,。另一件事是列类型可能不是基本类型,将有自定义数据类型,如AType、BType等,而不是int、string。那么,有没有一种方法可以应用这些自定义数据类型呢?能否详细介绍一下如何创建动态模式?您可以更新您的问题。:)非常感谢,这很有帮助,但是如果模式是以下类型的呢:?在这种情况下,我无法执行类型转换。|--C2:struct(nullable=true)|--Gender:string(nullable=true)是的,我也想使用我自己的模式,上面的with column/cast对基本类型有效,但是自定义模式如何,这个模式只有在运行时才知道…|--C0:integer(nullable=true)|--C1:integer(nullable=true)|--C2:struct(nullable=true)|--Gender:string(nullable=true)