我有一个Dataframe A,它包含一列数组字符串。
...
|-- browse: array (nullable = true)
| |-- element: string (containsNull = true)
...
例如,三个样本行将是
+---------+--------+---------+
| column 1| browse| column n|
+---------+--------+---------+
| foo1| [X,Y,Z]| bar1|
| foo2| [K,L]| bar2|
| foo3| [M]| bar3|
另一个包含字符串
列的Dataframe B.|-- browsenodeid: string (nullable = true)
它的一些示例行将是
+------------+
|browsenodeid|
+------------+
| A|
| Z|
| M|
如何过滤A以便保留browse
包含来自B的browsenodeid
的任何值的所有行?就上述例子而言,结果将是:
+---------+--=-----+---------+
| column 1| browse| column n|
+---------+--------+---------+
| foo1| [X,Y,Z]| bar1| <- because Z is a value of B.browsenodeid
| foo3| [M]| bar3| <- because M is a value of B.browsenodeid
如果我有一个值,那么我会使用像
这样的东西A.filter(array_contains(A("browse"), single_value))
但是我如何处理值列表或DataFrame呢?
答案 0 :(得分:5)
我找到了一个优雅的解决方案,无需将DataFrame
s / Dataset
转换为RDD
s。
假设您有一个DataFrame dataDF
:
+---------+--------+---------+
| column 1| browse| column n|
+---------+--------+---------+
| foo1| [X,Y,Z]| bar1|
| foo2| [K,L]| bar2|
| foo3| [M]| bar3|
以及包含您要在b
browse
val b: Array[String] = Array(M,Z)
实施udf:
def array_contains_any(s: Seq[String]): UserDefinedFunction = udf((c: WrappedArray[String]) => c.toList.intersect(s).nonEmpty)
然后只需使用filter
或where
函数(稍微有点花哨:P)进行过滤,如:
dataDF.where(array_contains_any(b)($"browse"))
答案 1 :(得分:0)
假设输入数据:Dataframe A
browse
200,300,889,767,9908,7768,9090
300,400,223,4456,3214,6675,333
234,567,890
123,445,667,887
并且您必须将其与Dataframe B匹配
browsenodeid :(我将列browsenodeid弄平)123,200,300
val matchSet = "123,200,300".split(",").toSet
val rawrdd = sc.textFile("D:\\Dataframe_A.txt")
rawrdd.map(_.split("|"))
.map(arr => arr(0).split(",").toSet.intersect(matchSet).mkString(","))
.foreach(println)
你的输出:
300,200
300
123
已更新
val matchSet = "A,Z,M".split(",").toSet
val rawrdd = sc.textFile("/FileStore/tables/mvv45x9f1494518792828/input_A.txt")
rawrdd.map(_.split("|"))
.map(r => if (! r(1).split(",").toSet.intersect(matchSet).isEmpty) org.apache.spark.sql.Row(r(0),r(1), r(2))).collect.foreach(println)
输出
foo1,X,Y,Z,bar1
foo3,M,bar3
答案 2 :(得分:0)
在Spark> = 2.4.0中,您可以使用arrays_overlap
:
import org.apache.spark.sql.functions.{array, arrays_overlap, lit}
val df = Seq(
("foo1", Seq("X", "Y", "Z"), "bar1"),
("foo2", Seq("K", "L"), "bar2"),
("foo3", Seq("M"), "bar3")
).toDF("col1", "browse", "coln")
val b = Seq("M" ,"Z")
val searchArray = array(b.map{lit}:_*) // cast to lit(i) then create Spark array
df.where(arrays_overlap($"browse", searchArray)).show()
// +----+---------+----+
// |col1| browse|coln|
// +----+---------+----+
// |foo1|[X, Y, Z]|bar1|
// |foo3| [M]|bar3|
// +----+---------+----+