【问题标题】:How to elegantly convert multi-col rows into dataframe?如何优雅地将多列行转换为数据框?
【发布时间】:2018-05-18 21:33:34
【问题描述】:

我想使用StructTypeRDD 转换为DataFrame。但是项目"Broken,Line," 会导致错误。有没有一种优雅的方式来处理这样的记录?谢谢。

import org.apache.spark.sql.types.{StructType, StructField, StringType}
import org.apache.spark.sql.Row

val mySchema = StructType(Array(
  StructField("colA", StringType, true),
  StructField("colB", StringType, true),
  StructField("colC", StringType, true)))
val x = List("97573,Start,eee", "9713,END,Good", "Broken,Line,")
val inputx = sc.parallelize(x).
| map((x:String) => Row.fromSeq(x.split(",").slice(0,mySchema.size).toSeq))
val df = spark.createDataFrame(inputx, mySchema)
df.show

错误是这样的:

名称:org.apache.spark.SparkException 消息:作业因以下原因中止 阶段失败:阶段 14.0 中的任务 0 失败 1 次,最近一次 失败:在 14.0 阶段丢失任务 0.0(TID 14,本地主机,执行程序 驱动程序):java.lang.RuntimeException:编码时出错: java.lang.ArrayIndexOutOfBoundsException: 2

我正在使用:

  • 火花:2.2.0
  • 斯卡拉:2.11.8

我在spark-shell 中运行了代码。

【问题讨论】:

  • 错误是什么?你的代码看起来不错。如果您担心那部分,可以使用x.split("," , -1)
  • @philantrovert 谢谢,我刚刚更新了我的问题

标签: apache-spark dataframe apache-spark-sql


【解决方案1】:

Row.fromSeq 我们在其上应用您的架构会引发您遇到的错误。列表中的第三个元素仅包含 2 个元素。除非添加空值而不是缺失值,否则无法将其转换为具有三个元素的 Row。

在创建 DataFrame 时,Spark 期望每行有 3 个元素在其上应用架构,因此会出现错误。

一个快速而肮脏的解决方案是使用scala.util.Try 分别获取字段:

import org.apache.spark.sql.types.{StructType, StructField, StringType}
import org.apache.spark.sql.Row
import scala.util.Try

val mySchema = StructType(Array(StructField("colA", StringType, true), StructField("colB", StringType, true), StructField("colC", StringType, true)))

val l = List("97573,Start,eee", "9713,END,Good", "Broken,Line,")

val rdd = sc.parallelize(l).map {
 x => {
  val fields = x.split(",").slice(0, mySchema.size)
  val f1 = Try(fields(0)).getOrElse("")
  val f2 = Try(fields(1)).getOrElse("")
  val f3 = Try(fields(2)).getOrElse("")
  Row(f1, f2, f3)
 }
}

val df = spark.createDataFrame(rdd, mySchema)

df.show
// +------+-----+----+
// |  colA| colB|colC|
// +------+-----+----+
// | 97573|Start| eee|
// |  9713|  END|Good|
// |Broken| Line|    |
// +------+-----+----+

我不会说这是一个优雅的解决方案,就像你问的那样。解析字符串从来都不是优雅的!您应该使用csv 源来正确读取它(或spark-csv 用于

【讨论】:

    猜你喜欢
    • 2016-02-17
    • 2010-12-17
    • 2013-04-02
    • 2020-05-21
    • 2022-11-17
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多