如何使用reduceByKey选择特定列的记录?

时间:2016-08-18 08:56:30

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

我有一个Dataframe,我想在其中删除基于密钥的重复项,catch是共享相同密钥的记录之一,我需要根据某些列而不是任何记录进行选择。

例如,我的DF看起来像:

+------+-------+-----+
|animal|country|color|
+------+-------+-----+
|   Cat|america|white|
|   dog|america|brown|
|   dog| canada|white|
|   dog| canada|black|
|   Cat| canada|black|
|  bear| canada|white|
+------+-------+-----+

现在我想删除基于动物列的重复项,然后选择国家'美国'。< / p>

我想要的输出应该是:

+------+-------+-----+
|animal|country|color|
+------+-------+-----+
|   Cat|america|white|
|   dog|america|brown|
|  bear| canada|white|
+------+-------+-----+

由于Dataframe api中没有reduceBykey,我将其转换为keyValue对rdd然后执行reduceBykey我陷入了将在重复项中进行基于首选项的选择的函数。

我更喜欢scala中的示例代码。

2 个答案:

答案 0 :(得分:0)

我相信你可以使用Windows在Spark版本&gt; = 1.4中使用DataFrames做你所做的事情(至少我认为这是他们所称的)。

但是使用RDD

val input: RDD[(String, String, Row)] = ???
val keyedByAnimal: RDD[(String, (String, Row))] = 
    input.map{case (animal, country, other) => (animal, (country, other)) }
val result: RDD[(String, (String, Row))] = keyedByAnimal.reduceByKey{(x, y) =>
    if(x._1 == "america") x else y
}

以上为每个动物值提供了一个不同的值。选择哪个值是非确定性的。关于它的所有可以说的是,如果动物的价值存在于美国&#34;其中一个将被选中。

关于你的评论:

val df: DataFrame = ???
val animalCol:String = ???
val countryCol: String = ???
val otherCols = df.columns.filter(c => c != animalCol && c!= countryCol)
val rdd: RDD[(String, String, Row)] = 
    df.select(animalCol, countryCol, otherCols:_ *).rdd.map(r => (r.getString(0), r.getString(1), r)

select重新排序列,以便getString方法提取预期值。 老实说,看看Window Aggregations。我不太了解他们,因为我不使用Dataframes或Spark超过1.3。

答案 1 :(得分:0)

对于所有动物种类(狗,猫,......),至少有一个国家“美国”的条目,并且你不介意在美国境内松散重复的匹配动物,你可以使用{{ 1}}:

reduceByKey

如果您的动物在“美国”中没有条目,则上面的代码将采用其中一个副本:最后一个。您可以通过提供在这些情况下维护重复项的结果来改进它。 e.g:

val animals = sc.parallelize(("cat","america", "white")::("dog","america","brown")::("dog","canada","white")::("dog","canada","black")::("cat","canada","black")::("bear","canada","white")::Nil)

val animalsKV = animals.map { case (k, a, b) => k -> (a,b) }

animalsKV.reduceByKey {
    case (a @ ("america",_ ), _) =>  a
    case (_, b) => b
}

可以修改该代码以跟踪重复的“美国”动物。