Spark:减去数据帧但保留重复值

时间:2017-04-23 00:04:44

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

假设我有两个Spark SQL数据帧AB。我想从B中的项目中减去A中的项目,同时保留A的重复项。

我按照说明使用了我在另一个StackOverflow问题("Spark: subtract two DataFrames")中找到的DataFrame.except(),但该函数会删除原始数据框A中的所有重复项。

作为一个概念性示例,如果我有两个数据帧:

words     = [the, quick, fox, a, brown, fox]
stopWords = [the, a]

然后我希望输出以任何顺序:

words - stopWords = [quick, brown, fox, fox]

我发现RDD函数subtract()保留了重复项,但Spark-SQL函数except()删除了结果数据框中的重复项。我不明白为什么except()输出只产生唯一值。

这是一个完整的演示:

// ---------------------------------------------------------------
// EXAMPLE USING RDDs
// ---------------------------------------------------------------
var wordsRdd = sc.parallelize(List("the", "quick", "fox", "a", "brown", "fox"))
var stopWordsRdd = sc.parallelize(List("a", "the"))

var wordsWithoutStopWordsRdd = wordsRdd.subtract(stopWordsRdd)
wordsWithoutStopWordsRdd.take(10)
// res11: Array[String] = Array(quick, brown, fox, fox)

// ---------------------------------------------------------------
// EXAMPLE USING DATAFRAMES
// ---------------------------------------------------------------
var wordsDf = wordsRdd.toDF()
var stopWordsDf = stopWords.toDF()
var wordsWithoutStopWordsDf = wordsDf.except(stopWordsDf)

wordsWithoutStopWordsDf.show(10)
// +-----+
// |value|
// +-----+
// |  fox|
// |brown|
// |quick|
// +-----+

我想保留重复项,因为我正在生成频率表。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

val words = sc.parallelize(List("the", "quick", "fox", "a", "brown", "fox")).toDF("id")
val stopwords = sc.parallelize(List("a", "the")).toDF("id")


words.join(stopwords, words("id") === stopwords("id"), "left_outer")
     .where(stopwords("id").isNull)
     .select(words("id")).show()

输出结果为:

+-----+
|   id|
+-----+
|  fox|
|  fox|
|brown|
|quick|
+-----+