Spark,DataFrame:从许多列中获取所有不同的字符串

时间:2017-12-15 10:49:34

标签: apache-spark apache-spark-sql spark-dataframe

数据DataFrame有15个字符串列。

目标:创建一个包含所有15列中不同字符串的列表。

示例:如果单词"吉他"在第一列和第四列中出现一次或多次,它必须在最终列表中出现一次。

建议的解决方案但不理想:UDF是一个选项,用于连接一个新列中的所有列,然后我可以使用CountVectorizer处理该列,从而提取词汇表。但UDF是有限的,因为它们接受最多10个输入参数(即我不能将超过10列传递给UDF),因此该解决方案必须实现两个UDF,第一个连接10个列,第二个连接到UDF将第一个UDF的输出与接下来的5列连接起来。

我正在为这个问题寻找一种更有效的紧凑型解决方案,更一般地说,是针对UDF输入参数数量有限的解决方案。

1 个答案:

答案 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)