如何使用Spark DataFrame处理自定义NULL字符串

时间:2016-04-20 06:15:15

标签: apache-spark

我的数据文件如下所示:

// data.txt
1    2016-01-01
2    \N
3    2016-03-01

由于某种原因,我使用\N来表示空值。 (它不是一个特殊字符,它是一个由2个字符组成的字符串:\N)。

我想创建如下的DataFrame:

case class Data(
    val id   : Int, 
    val date : java.time.LocalDate)

val df = sc.textFile("data.txt")
           .map(_.split("\t"))
           .map(p => Data(
               p(0).toInt, 
               _helper(p(1))
           ))
           .toDF()

我的问题是如何编写辅助方法?

def _helper(s : String) = s match {
    case "\\N" => null,                // type error             
    case _     => LocalDate.parse(s, dateFormat) 
}

1 个答案:

答案 0 :(得分:1)

这是Option类型派上用场的地方。

我更改了自定义null值以使案例更加明确,但它应该适用于您的情况。我的数据是这样的.txt文件:

Ryan,11
Bob,22
Kevin,23
Asop,-nnn-

请注意-nnn-是我的自定义null。我使用了略有不同的案例类:

case class DataSet(name: String, age: Option[Int])

并编写一个模式匹配函数来捕捉情况的细微差别:

      def customNull (col: String): Option[Int] = col match {
           case "-nnn-" => None
           case _ => Some(Integer.parseInt(col))
      }

从这里开始,当你将两者合并时,它应该按预期工作:

  val df = sc.textFile("./data.txt")
.map(_.split(","))
.map(p=>DataSet(p(0), customNull(p(1))))
.toDF()

当我执行df.show()时,我得到以下内容:

+-----+----+
| name| age|
+-----+----+
| Ryan|  11|
|  Bob|  22|
|Kevin|  23|
| Asop|null|
+-----+----+

像字符串一样对待年龄可以解决问题。解析这样的值可能不是最快的。理想情况下,您也可以使用Either,但也可能会变得复杂。