如何基于spark数据帧中的某些列过滤掉重复的行?

时间:2017-03-28 05:23:57

标签: apache-spark apache-spark-dataset

假设我有一个如下的数据框:

enter image description here

在这里,您可以看到事务编号1,2和3对于列A,B,C具有相同的值,但对于列D和E具有不同的值。列E具有日期条目。

  1. 对于相同的A,B和C组合(A = 1,B = 1,C = 1),我们有3行。我想根据最近的E行事务日期只占一行,这意味着具有最新日期的行。但是对于最近的日期,有2笔交易。但是如果在A列中找到A,B,C和最近日期的相同组合的两行或更多行,我想只取其中一行。 所以这个组合的预期输出将是行号 3或4 (任何人都可以)。
  2. 对于相同的A,B和C组合(A = 2,B = 2,C = 2),我们有2行。但是基于E列,最近的日期是第5行的日期。所以我们将把这一行用于A,B和C的这个组合。 所以这个组合的预期输出将是行号 5
  3. 所以最终输出将是(3和5)(4和5)

    现在应该如何处理:

    1. 我读到了这个:
    2.   

      reduceByKey和groupByKey都可以用于相同的目的但是   reduceByKey在大型数据集上运行得更好。那是因为Spark   知道它可以将输出与每个分区上的公共密钥组合起来   洗牌数据。

      1. 我尝试使用groupBy在列A上的A,B,C和max列。但如果同一日期存在多行,则无法给出行的开头。
      2. 解决此问题的最佳方法是什么?提前致谢。

        编辑:我需要取回已过滤的交易。怎么做呢?

3 个答案:

答案 0 :(得分:0)

可通过几个步骤进行链接。 Agregated Dataframe:

val agregatedDF=initialDF.select("A","B","C","E").groupBy("A","B","C").agg(max("E").as("E_max"))

链接intial-agregated:

initialDF.join(agregatedDF, List("A","B","C"))

如果初始DataFrame来自Hive,则所有内容都可以简化。

答案 1 :(得分:0)

val initialDF = Seq((1,1,1,1,"2/28/2017 0:00"),(1,1,1,2,"3/1/2017 0:00"),
(1,1,1,3,"3/1/2017 0:00"),(2,2,2,1,"2/28/2017 0:00"),(2,2,2,2,"2/25/20170:00")) 

这将错过相应的col(D)

initialDF
.toDS.groupBy("_1","_2","_3")
.agg(max(col("_5"))).show 

如果您想要max col的相应colD:

 initialDF.toDS.map(x=>x._1,x._2,x._3,x._5,x._4))).groupBy("_1","_2","_3")
.agg(max(col("_4")).as("_4")).select(col("_1"),col("_2"),col("_3"),col("_4._2"),col("_4._1")).show

对于ReduceByKey,您可以将数据集转换为pairRDD然后解决它。如果Catalyst无法在第一个中优化groupByKey,应该更快。请参阅Rolling your own reduceByKey in Spark Dataset

答案 2 :(得分:0)

我使用spark window functions来获取解决方案:

 val window = Window
      .partitionBy(dataframe("A"), dataframe("B"),dataframe("C"))
      .orderBy(dataframe("E") desc)

 val dfWithRowNumber = dataframe.withColumn("row_number", row_number() over window)
 val filteredDf = dfWithRowNumber.filter(dfWithRowNumber("row_number") === 1)