Scala 删除spark数据框中重复的所有记录

Scala 删除spark数据框中重复的所有记录,scala,apache-spark,duplicates,apache-spark-sql,spark-dataframe,Scala,Apache Spark,Duplicates,Apache Spark Sql,Spark Dataframe,我有一个spark数据框,里面有多列。我想找出并删除列中具有重复值的行(其他列可能不同) 我尝试使用dropDuplicates(col\u name)但它只会删除重复的条目,但仍会在数据帧中保留一条记录。我需要的是删除最初包含重复条目的所有条目 我使用的是Spark 1.6和Scala 2.10。这可以通过按列分组来完成,以在中查找重复项,然后聚合并过滤结果 示例数据帧df: +---+---+ | id|num| +---+---+ | 1| 1| | 2| 2| | 3| 3|

我有一个spark数据框,里面有多列。我想找出并删除列中具有重复值的行(其他列可能不同)

我尝试使用
dropDuplicates(col\u name)
但它只会删除重复的条目,但仍会在数据帧中保留一条记录。我需要的是删除最初包含重复条目的所有条目


我使用的是Spark 1.6和Scala 2.10。

这可以通过按列分组来完成,以在中查找重复项,然后聚合并过滤结果

示例数据帧
df

+---+---+
| id|num|
+---+---+
|  1|  1|
|  2|  2|
|  3|  3|
|  4|  4|
|  4|  5|
+---+---+
id
列分组以删除重复项(最后两行):

这将为您提供:

+---+---+
| id|num|
+---+---+
|  1|  1|
|  2|  2|
|  3|  3|
+---+---+

或者,也可以使用
连接来完成。这样会比较慢,但是如果有很多列,就不需要先使用
first($“num”).as(“num”)
来保存它们

val df2 = df.groupBy("id").agg(count($"id").as("count")).filter($"count" === 1).select("id")
val df3 = df.join(df2, Seq("id"), "inner")

我会使用窗口函数来实现这一点。假设要删除重复的
id
行:

import org.apache.spark.sql.expressions.Window

df
  .withColumn("cnt", count("*").over(Window.partitionBy($"id")))
  .where($"cnt"===1).drop($"cnt")
  .show()

我在使用@Raphael Roth解决方案的开源库中添加了一个
killDuplicates()
方法。下面是如何使用代码:

import com.github.mrpowers.spark.daria.sql.DataFrameExt._

df.killDuplicates(col("id"))

// you can also supply multiple Column arguments
df.killDuplicates(col("id"), col("another_column"))
下面是代码实现:

object DataFrameExt {

  implicit class DataFrameMethods(df: DataFrame) {

    def killDuplicates(cols: Column*): DataFrame = {
      df
        .withColumn(
          "my_super_secret_count",
          count("*").over(Window.partitionBy(cols: _*))
        )
        .where(col("my_super_secret_count") === 1)
        .drop(col("my_super_secret_count"))
    }

  }

}

您可能希望利用spark daria库将此逻辑排除在代码库之外。

如果我理解正确,您希望删除在单个列中重复的所有条目吗?或者在考虑多个列时它们是重复的?@shaido是的,这些列的所有条目都在单个列中重复。在scala中,如下所示,我想在Python中应该有类似的方法来实现这一点,希望这有助于-获取列名:val columns=df.schema.map(u.name)-在该列列表上运行foldLeft:columns.foldLeft(df)((acc,elem)=>acc.dropDuplicates(elem))我看到您删除了pyspark标记并添加了您正在使用Scala,因此我更改了答案以反映这一点。由于您正在检查分组列的计数==1,连接不能替换为
first($“num”)。作为(“num”)
?它应该会产生相同的输出。@philantrovert这是一个很好的观点,我不确定我怎么会错过它。我更改了答案以考虑到这一点。@shaido您的解决方案也很有效,但我希望避免为这个问题创建另一个数据帧,这就是为什么接受raphael的解决方案ans@salmanbw但是第一种方法不会创建任何额外的数据帧?唯一的区别是,这个人使用
groupBy
agg
,而他使用窗口函数来获得结果。我尝试了随机生成数据,用户应该注意。persist可能是相关的。
object DataFrameExt {

  implicit class DataFrameMethods(df: DataFrame) {

    def killDuplicates(cols: Column*): DataFrame = {
      df
        .withColumn(
          "my_super_secret_count",
          count("*").over(Window.partitionBy(cols: _*))
        )
        .where(col("my_super_secret_count") === 1)
        .drop(col("my_super_secret_count"))
    }

  }

}