按字段Scala中的值过滤rdd行

时间:2017-03-13 18:27:18

标签: scala apache-spark

我有一个具有以下结构的csv:

  

头,报头,报头,报头,报头
  val1,val2,val3,val4,val5
  val1,val2,null,val4,val5
  val1,val2,val3,null,val5

我需要做的是过滤掉在特定位置包含空值的标题和数据行(可以在val3但不是val4时为null)。我做了一个rdd并在逗号上分割了这些行,我希望能像访问数组的索引位置一样访问每一行。但我无法找到如何进行比较。我可以用以下内容提取字段:

  

rdd.map(values =>(values(2))

你是如何进行比较的?特别是“不包含”。我认为有比较方法可用或这个问题需要一个元组和!包含?

3 个答案:

答案 0 :(得分:3)

假设您已经定义了用于包装这些值的类型,请说:

case class Record(val1: String, val2: Option[String], val3: String, val4: Option[String])

val rdd: RDD[Record] = ...
rdd.filter(record => record.val2.isDefined && record.val4.isDefined)

我希望这会有所帮助。

答案 1 :(得分:2)

如果您使用DataFrame而不是RDD,则可以使用filter和布尔Column操作。

假设val4val5都不应为空。

如果您的csv看起来像这样:

evan@vbox ~ > cat dat_1.csv
header1,header2,header3,header4,header5
val1,val2,val3,val4,val5
val1,val2,,val4,val5
val1,val2,val3,,val5

然后你的代码看起来像:

scala> val dat_1 = spark.read.option("header", true).csv("dat_1.csv")
dat_1: org.apache.spark.sql.DataFrame = [header1: string, header2: string ... 3 more fields]

scala> dat_1.show
+-------+-------+-------+-------+-------+
|header1|header2|header3|header4|header5|
+-------+-------+-------+-------+-------+
|   val1|   val2|   val3|   val4|   val5|
|   val1|   val2|   null|   val4|   val5|
|   val1|   val2|   val3|   null|   val5|
+-------+-------+-------+-------+-------+


scala> data1.filter($"header4".isNotNull && $"header5".isNotNull).show
+-------+-------+-------+-------+-------+
|header1|header2|header3|header4|header5|
+-------+-------+-------+-------+-------+
|   val1|   val2|   val3|   val4|   val5|
|   val1|   val2|   null|   val4|   val5|
+-------+-------+-------+-------+-------+

否则,如果您的数据如下所示:

evan@vbox ~ > cat dat_2.csv
header1,header2,header3,header4,header5
val1,val2,val3,val4,val5
val1,val2,null,val4,val5
val1,val2,val3,null,val5

然后你的代码看起来像这样:

scala> val dat_2 = spark.read.option("header", true).csv("dat_2.csv")
dat_2: org.apache.spark.sql.DataFrame = [header1: string, header2: string ... 3 more fields]

scala> dat_2.show
+-------+-------+-------+-------+-------+
|header1|header2|header3|header4|header5|
+-------+-------+-------+-------+-------+
|   val1|   val2|   val3|   val4|   val5|
|   val1|   val2|   null|   val4|   val5|
|   val1|   val2|   val3|   null|   val5|
+-------+-------+-------+-------+-------+


scala> dat_2.filter($"header4" =!= "null" && $"header5" =!= "null").show
+-------+-------+-------+-------+-------+
|header1|header2|header3|header4|header5|
+-------+-------+-------+-------+-------+
|   val1|   val2|   val3|   val4|   val5|
|   val1|   val2|   null|   val4|   val5|
+-------+-------+-------+-------+-------+

答案 2 :(得分:0)

输入文件中的空值不能通过在文件中的表示方式来表示:

header,header,header,header,header
val1, val2, val3, val4, val5
val1, val2, null, val4, val5
val1, val2, val3, null, val5

应该是这样的:

header,header,header,header,header
val1, val2, val3, val4, val5
val1, val2, null, val4, val5
val1, val2, val3,, val5

解决方案:使用mapPartitionsWithIndex删除第一个迭代器作为第0个索引将过滤输入文件中的标头,而在第4个字段中使用!=“”将过滤掉第3行

**scala>** sc.textFile("/User/VJ/testfile").
mapPartitionsWithIndex((x,y) => if (x==0) y.drop(1) else y).
filter(x=>x.split(",")(3) != "" ).
take(5).foreach(println)

必需的输出:

val1, val2, val3, val4, val5
val1, val2, null, val4, val5

此处示例 https://tips-to-code.blogspot.com/2018/08/nulls-in-scala-spark.html

谢谢, 维沙尔。