我想过滤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过滤通用数组,只知道过滤值...
答案 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| []|
+----+----+--------+