向Scala Spark中的Row添加新的utf8字符串列时出错

时间:2019-06-28 17:26:15

标签: scala apache-spark

我正在尝试像这样在DataFrame的每一行中添加一个新列

  def addNamespace(iter: Iterator[Row]): Iterator[Row] = {
    iter.map (row => {
      println(row.getString(0))
//      Row.fromSeq(row.toSeq ++ Array[String]("shared"))

      val newseq = row.toSeq ++ Array[String]("shared")
      Row(newseq: _*)
    })
    iter
  }

  def transformDf(source: DataFrame)(implicit spark: SparkSession): DataFrame = {
    val newSchema = StructType(source.schema.fields ++ Array(StructField("namespace", StringType, nullable = true)))
    val df = spark.sqlContext.createDataFrame(source.rdd.mapPartitions(addNamespace), newSchema)
    df.show()
    df

  }

但是我一直收到此错误-Caused by: java.lang.RuntimeException: org.apache.spark.unsafe.types.UTF8String is not a valid external type for schema of string行中的df.show()

有人可以帮忙弄清楚这个问题吗?我搜索了多个帖子,但尝试所做的一切都给了我这个错误。

我也尝试过val again = sourceDF.withColumn("namespace", functions.lit("shared")),但是它有相同的问题。

已读取数据的模式

root
 |-- name: string (nullable = true)
 |-- data: struct (nullable = true)
 |    |-- name: string (nullable = true)
 |    |-- description: string (nullable = true)
 |    |-- activates_on: timestamp (nullable = true)
 |    |-- expires_on: timestamp (nullable = true)
 |    |-- created_by: string (nullable = true)
 |    |-- created_on: timestamp (nullable = true)
 |    |-- updated_by: string (nullable = true)
 |    |-- updated_on: timestamp (nullable = true)
 |    |-- properties: map (nullable = true)
 |    |    |-- key: string
 |    |    |-- value: string (valueContainsNull = true)

1 个答案:

答案 0 :(得分:1)

  

由于:java.lang.RuntimeException:   org.apache.spark.unsafe.types.UTF8String不是有效的外部类型   用于字符串模式

表示对于新添加的“名称空间”列,其无法理解为字符串类型...。

清楚地表明催化剂级别的数据类型不匹配错误...

请参见火花代码here

override def eval(input: InternalRow): Any = {
    val result = child.eval(input)
    if (checkType(result)) {
      result
    } else {
      throw new RuntimeException(s"${result.getClass.getName}$errMsg")
    }
  }

,错误消息为s" is not a valid external type for schema of ${expected.catalogString}"

因此,UTF字符串不是真正的字符串,在将其作为字符串类型传递之前,您需要对其进行编码/解码,否则催化剂将无法理解您正在传递的内容。

  

如何修复?

下面是SO内容,将介绍如何将utfstring编码/从utfstring转换为字符串,反之亦然...您可能需要为此应用合适的解决方案。

https://stackoverflow.com/a/5943395/647053 string decode utf-8

注意: online UTF-8 encoder/decoder tool非常方便放置示例数据并将其转换为字符串。先尝试一下。...