我有一个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中的示例代码。
答案 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
}
可以修改该代码以跟踪重复的“美国”动物。