数据:DataFrame
有15个字符串列。
目标:创建一个包含所有15列中不同字符串的列表。
示例:如果单词"吉他"在第一列和第四列中出现一次或多次,它必须在最终列表中出现一次。
建议的解决方案但不理想:UDF是一个选项,用于连接一个新列中的所有列,然后我可以使用CountVectorizer
处理该列,从而提取词汇表。但UDF是有限的,因为它们接受最多10个输入参数(即我不能将超过10列传递给UDF),因此该解决方案必须实现两个UDF,第一个连接10个列,第二个连接到UDF将第一个UDF的输出与接下来的5列连接起来。
我正在为这个问题寻找一种更有效的紧凑型解决方案,更一般地说,是针对UDF输入参数数量有限的解决方案。
答案 0 :(得分:4)
spark-sql函数array
可以将任意数量的冒号(相同类型)映射到该类型的数组列。
从那时起,您可以在数组类型上创建UDF,或者根据您的情况,按照建议使用CountVectorizer。
scala> val data = spark.sparkContext.parallelize(Seq(("a1", "b1", "c1"), ("a2", "b2", "c2"))).toDF("a", "b", "c")
data: org.apache.spark.sql.DataFrame = [a: string, b: string ... 1 more field]
scala> data.show
+---+---+---+
| a| b| c|
+---+---+---+
| a1| b1| c1|
| a2| b2| c2|
+---+---+---+
scala> data.select(array("a", "b", "c")).show
+--------------+
|array(a, b, c)|
+--------------+
| [a1, b1, c1]|
| [a2, b2, c2]|
+--------------+
然而,比CountVectorizer更简单:
scala> data.select(explode(array("a", "b", "c"))).distinct.show
+---+
|col|
+---+
| b2|
| c1|
| a2|
| b1|
| a1|
| c2|
+---+
如果你直接使用RDD就可以了,那么仍然可以更简单(也可能更快):
scala> data.rdd.flatMap(r=>r.toSeq).distinct.collect
res4: Array[Any] = Array(b2, a1, a2, c1, c2, b1)