Scala-Spark(version1.5.2) 数据帧拆分错误

qwe*_*rty 4 scala apache-spark spark-dataframe

我有一个foo.txt包含以下内容的输入文件:

c1|c2|c3|c4|c5|c6|c7|c8|
00| |1.0|1.0|9|27.0|0||
01|2|3.0|4.0|1|10.0|1|1|
Run Code Online (Sandbox Code Playgroud)

我想将其转换为 aDataframe以执行一些Sql查询:

var text = sc.textFile("foo.txt")
var header = text.first()
var rdd = text.filter(row => row != header)
case class Data(c1: String, c2: String, c3: String, c4: String, c5: String, c6: String, c7: String, c8: String)
Run Code Online (Sandbox Code Playgroud)

到此为止一切正常,问题出在下一句:

var df = rdd.map(_.split("\\|")).map(p => Data(p(0), p(1), p(2), p(3), p(4), p(5), p(6), p(7))).toDF()
Run Code Online (Sandbox Code Playgroud)

如果我尝试打印dfdf.show,我得到一个错误信息:

scala> df.show()
java.lang.ArrayIndexOutOfBoundsException: 7
Run Code Online (Sandbox Code Playgroud)

我知道错误可能是由于拆分句子造成的。我还尝试foo.txt使用以下语法进行拆分:

var df = rdd.map(_.split("""|""")).map(p => Data(p(0), p(1), p(2), p(3), p(4), p(5), p(6), p(7))).toDF()
Run Code Online (Sandbox Code Playgroud)

然后我得到这样的东西:

scala> df.show()
+------+---------+----------+-----------+-----+-----------+----------------+----------------+
|  c1  |     c2  |    c3    |     c4    |  c5 |     c6    |        c7      |       c8       |
+------+---------+----------+-----------+-----+-----------+----------------+----------------+
|     0|        0|         ||           |    ||          1|               .|               0|
|     0|        1|         ||          2|    ||          3|               .|               0|
+------+---------+----------+-----------+-----+-----------+----------------+----------------+
Run Code Online (Sandbox Code Playgroud)

因此,我的问题是如何正确地将此文件传递给 Dataframe。

编辑:由于||没有中间空格的字段,错误在第一行。这种类型的字段定义取决于示例工作正常或崩溃。

jam*_*rta 5

这是因为您的一行比其他行短:

scala> var df = rdd.map(_.split("\\|")).map(_.length).collect()
df: Array[Int] = Array(7, 8)
Run Code Online (Sandbox Code Playgroud)

您可以手动填写行(但您需要手动处理每个案例):

val df = rdd.map(_.split("\\|")).map{row =>
  row match {
    case Array(a,b,c,d,e,f,g,h) => Data(a,b,c,d,e,f,g,h)
    case Array(a,b,c,d,e,f,g) => Data(a,b,c,d,e,f,g," ")
  }
}

scala> df.show()
+---+---+---+---+---+----+---+---+
| c1| c2| c3| c4| c5|  c6| c7| c8|
+---+---+---+---+---+----+---+---+
| 00|   |1.0|1.0|  9|27.0|  0|   |
| 01|  2|3.0|4.0|  1|10.0|  1|  1|
+---+---+---+---+---+----+---+---+
Run Code Online (Sandbox Code Playgroud)

编辑:

更通用的解决方案是这样的:

val df = rdd.map(_.split("\\|", -1)).map(_.slice(0,8)).map(p => Data(p(0), p(1), p(2), p(3), p(4), p(5), p(6), p(7))).toDF()
Run Code Online (Sandbox Code Playgroud)

如果您假设您始终拥有正确数量的分隔符,则使用此语法截断最后一个值是安全的。