仅了解过滤条件时对通用数据通用数组进行火花过滤器

时间:2018-08-07 08:09:50

标签: scala apache-spark apache-spark-sql

我想过滤Spark sql.DataFrame,而只留下所需的数组元素,而无需事先了解整个架构(不想对其进行硬编码)。 架构:

root
 |-- callstartcelllabel: string (nullable = true)
 |-- calltargetcelllabel: string (nullable = true)
 |-- measurements: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- enodeb: string (nullable = true)
 |    |    |-- label: string (nullable = true)
 |    |    |-- ltecelloid: long (nullable = true)
 |-- networkcode: long (nullable = true)
 |-- ocode: long (nullable = true)
 |-- startcelllabel: string (nullable = true)
 |-- startcelloid: long (nullable = true)
 |-- targetcelllabel: string (nullable = true)
 |-- targetcelloid: long (nullable = true)
 |-- timestamp: long (nullable = true)

我只希望整个根具有特定的度量(已过滤),并且根在过滤后必须至少包含一个。

我有这个根的数据框,并且我有一个过滤值的数据框(一列)。

因此,例如:我只会知道我的根目录包含Measurements数组,而该数组包含标签。因此,我希望具有包含标签(“ label1”,“ label2”)的整个度量的整个根。

使用explode和collect_list进行的最后一次测试导致:将表达式分组为空,并且'callstartcelllabel'不是聚合函数...甚至可以归纳出这种过滤情况吗?不知道这种通用udaf应该是什么样子。

Spark的新功能。

编辑:

我来到的当前解决方案是:

爆炸数组->使用不需要的数组成员过滤掉不需要的行->除数组成员以外的所有分组-> agg。(collect_list(col(“ measurements”))

使用udf会更快吗?我不知道如何制作通用的udf过滤通用数组,只知道过滤值...

2 个答案:

答案 0 :(得分:0)

case class Test(a:Int,b:Int) // declared case class to show above scenario
var df=List((1,2,Test(1,2)),(2,3,Test(3,4)),(4,2,Test(5,6))).toDF("name","rank","array")
 +----+----+------+
 |name|rank| array|
 +----+----+------+
 |   1|   2|[1, 2]|
 |   2|   3|[3, 4]|
 |   4|   2|[5, 6]|
 +----+----+------+
df.printSchema
 //dataFrame structure look like this 
 root
|-- name: integer (nullable = false)
|-- rank: integer (nullable = false)
|-- array: struct (nullable = true)
|    |-- a: integer (nullable = false)
|    |-- b: integer (nullable = false)

df.filter(df("array")("a")>1).show
//after filter on dataFrame on specified condition
 +----+----+------+
 |name|rank| array|
 +----+----+------+
 |   2|   3|[3, 4]|
 |   4|   2|[5, 6]|
 +----+----+------+

//Above code help you to understand the Scenario

//use this piece of code:
 df.filter(df("measurements")("label")==="label1" || df("measurements")("label")==="label2).show

答案 1 :(得分:0)

 import org.apache.spark.sql.Row
 import org.apache.spark.sql.functions.udf
var df=Seq((1,2,Array(Test(1,2),Test(5,6))),(1,3,Array(Test(1,2),Test(5,3))),(10,11,Array(Test(1,6)))).toDF("name","rank","array")
 df.show
+----+----+----------------+
|name|rank|           array|
+----+----+----------------+
|   1|   2|[[1, 2], [5, 6]]|
|   1|   3|[[1, 2], [5, 3]]|
|  10|  11|        [[1, 6]]|
+----+----+----------------+
def test={
   udf((a:scala.collection.mutable.WrappedArray[Row])=> {
   val b=a.toArray.map(x=>(x.getInt(0),x.getInt(1)))
   b.filter(y=>y._1>1)
   })}
 df.withColumn("array",test(df("array"))).show
+----+----+--------+
|name|rank|   array|
+----+----+--------+
|   1|   2|[[5, 6]]|
|   1|   3|[[5, 3]]|
|  10|  11|      []|
+----+----+--------+