Scala Spark中同一Spark Dataframe列上的顺序动态过滤器

时间:2018-12-13 16:40:45

标签: scala apache-spark

我有一个名为root的列,需要根据根列的不同值来过滤数据框。

假设我在root中有一个值为parent,child或sub-child,我想通过一个变量动态应用这些过滤器。

val x = ("parent,child,sub-child").split(",")
x.map(eachvalue <- {

   var df1 = df.filter(col("root").contains(eachvalue))

}

但是当我这样做时,它总是改写DF1,我想应用所有3个过滤器并获得结果。

将来,我可能会将列表扩展到任意数量的过滤器值,并且代码应该可以工作。

谢谢, 宝贝

5 个答案:

答案 0 :(得分:2)

您应将后续过滤器应用于上一个过滤器的结果,而不是应用于df

val x = ("parent,child,sub-child").split(",")
var df1 = df
x.map(eachvalue <- {
    df1 = df1.filter(col("root").contains(eachvalue))
}

df1将在地图操作之后应用所有过滤器。

答案 1 :(得分:1)

让我们看一个使用spark shell的示例。希望对您有帮助。

scala> import spark.implicits._
import spark.implicits._

scala> val df0 = 
spark.sparkContext.parallelize(List(1,2,1,3,3,2,1)).toDF("number")
df0: org.apache.spark.sql.DataFrame = [number: int]

scala> val list = List(1,2,3)
list: List[Int] = List(1, 2, 3)


scala> val dfFiltered = for (number <- list) yield { df0.filter($"number" === number)}
dfFiltered: List[org.apache.spark.sql.Dataset[org.apache.spark.sql.Row]] = List([number: int], [number: int], [number: int])

scala> dfFiltered(0).show
+------+
|number|
+------+
|     1|
|     1|
|     1|
+------+


scala> dfFiltered(1).show
+------+
|number|
+------+
|     2|
|     2|
+------+


scala> dfFiltered(2).show
+------+
|number|
+------+
|     3|
|     3|
+------+

答案 2 :(得分:1)

在这种情况下可以使用AFAIK isin,下面是示例。

import spark.implicits._

val colorStringArr = "red,yellow,blue".split(",")
val colorDF =
  List(
    "red",
    "yellow",
    "purple"
  ).toDF("color")
// to derive a column using a list
colorDF.withColumn(
  "is_primary_color",
  col("color").isin(colorStringArr: _*)
).show()


     println( "if you don't want derived column and directly want to   filter using a list with isin then .. ")
    colorDF.filter(col("color").isin(colorStringArr: _*)).show

结果:

+------+----------------+
| color|is_primary_color|
+------+----------------+
|   red|            true|
|yellow|            true|
|purple|           false|
+------+----------------+

如果您不希望派生的列,而直接希望使用带有isin的列表进行过滤,那么....

+------+
| color|
+------+
|   red|
|yellow|
+------+

答案 3 :(得分:0)

使用array_contains和交换参数的另一种方法。

scala> val x = ("parent,child,sub-child").split(",")
x: Array[String] = Array(parent, child, sub-child)

scala> val df = Seq(("parent"),("grand-parent"),("child"),("sub-child"),("cousin")).toDF("root")
df: org.apache.spark.sql.DataFrame = [root: string]

scala> df.show
+------------+
|        root|
+------------+
|      parent|
|grand-parent|
|       child|
|   sub-child|
|      cousin|
+------------+


scala> df.withColumn("check", array_contains(lit(x),'root)).show
+------------+-----+
|        root|check|
+------------+-----+
|      parent| true|
|grand-parent|false|
|       child| true|
|   sub-child| true|
|      cousin|false|
+------------+-----+


scala>

答案 4 :(得分:0)

这是我的两分钱

val filters = List(1,2,3)
val data = List(5,1,2,1,3,3,2,1,4)
val colName = "number"
val df = spark.
  sparkContext.
  parallelize(data).
  toDF(colName).
  filter(
     r => filters.contains(r.getAs[Int](colName))
  )

df.show()

结果

+------+
|number|
+------+
|     1|
|     2|
|     1|
|     3|
|     3|
|     2|
|     1|
+------+