根据RDD / Spark DataFrame

时间:2015-05-14 22:03:24

标签: apache-spark apache-spark-sql pyspark

让我们说我有一个相当大的数据集,如下所示:

data = sc.parallelize([('Foo',41,'US',3),
                       ('Foo',39,'UK',1),
                       ('Bar',57,'CA',2),
                       ('Bar',72,'CA',2),
                       ('Baz',22,'US',6),
                       ('Baz',36,'US',6)])

我想要做的是仅根据第一,第三和第四列的值删除重复的行。

删除完全重复的行很简单:

data = data.distinct()

将删除第5行或第6行

但是,我如何仅根据第1,3和4列删除重复的行?即删除其中一个:

('Baz',22,'US',6)
('Baz',36,'US',6)

在Python中,可以通过使用.drop_duplicates()指定列来完成此操作。我怎样才能在Spark / Pyspark中实现同样的目标?

6 个答案:

答案 0 :(得分:49)

Pyspark 包含as方法。 https://spark.apache.org/docs/latest/api/python/pyspark.sql.html#pyspark.sql.DataFrame.dropDuplicates

null

也许它是在@Jason(OP)使用的后续版本中引入的?

编辑:是的,它是在1.4

中引入的

答案 1 :(得分:23)

根据您的问题,您不清楚要使用哪些列来确定重复项。解决方案背后的一般思想是根据标识重复项的列的值创建密钥。然后,您可以使用reduceByKey或reduce操作来消除重复项。

以下是一些可以帮助您入门的代码:

def get_key(x):
    return "{0}{1}{2}".format(x[0],x[2],x[3])

m = data.map(lambda x: (get_key(x),x))

现在,您有一个键值RDD,由第1,3和4列键入。 下一步可能是reduceByKeygroupByKeyfilter。 这样可以消除重复。

r = m.reduceByKey(lambda x,y: (x))

答案 2 :(得分:11)

我知道你已经接受了另一个答案,但是如果你想这样做的话 DataFrame,只需使用groupBy和agg。假设你已经创建了一个DF(列名为“col1”,“col2”等),你可以这样做:

myDF.groupBy($"col1", $"col3", $"col4").agg($"col1", max($"col2"), $"col3", $"col4")

请注意,在这种情况下,我选择了最大col2,但你可以做avg,min等。

答案 3 :(得分:9)

我使用了内置函数dropDuplicates()。 Scala代码如下所示

val data = sc.parallelize(List(("Foo",41,"US",3),
("Foo",39,"UK",1),
("Bar",57,"CA",2),
("Bar",72,"CA",2),
("Baz",22,"US",6),
("Baz",36,"US",6))).toDF("x","y","z","count")

data.dropDuplicates(Array("x","count")).show()

输出:

+---+---+---+-----+
|  x|  y|  z|count|
+---+---+---+-----+
|Baz| 22| US|    6|
|Foo| 39| UK|    1|
|Foo| 41| US|    3|
|Bar| 57| CA|    2|
+---+---+---+-----+

答案 4 :(得分:0)

以下程序将帮助您整体删除重复项,或者如果您想根据某些列删除重复项,您甚至可以这样做:

import org.apache.spark.sql.SparkSession

object DropDuplicates {
def main(args: Array[String]) {
val spark =
  SparkSession.builder()
    .appName("DataFrame-DropDuplicates")
    .master("local[4]")
    .getOrCreate()

import spark.implicits._

// create an RDD of tuples with some data
val custs = Seq(
  (1, "Widget Co", 120000.00, 0.00, "AZ"),
  (2, "Acme Widgets", 410500.00, 500.00, "CA"),
  (3, "Widgetry", 410500.00, 200.00, "CA"),
  (4, "Widgets R Us", 410500.00, 0.0, "CA"),
  (3, "Widgetry", 410500.00, 200.00, "CA"),
  (5, "Ye Olde Widgete", 500.00, 0.0, "MA"),
  (6, "Widget Co", 12000.00, 10.00, "AZ")
)
val customerRows = spark.sparkContext.parallelize(custs, 4)

// convert RDD of tuples to DataFrame by supplying column names
val customerDF = customerRows.toDF("id", "name", "sales", "discount", "state")

println("*** Here's the whole DataFrame with duplicates")

customerDF.printSchema()

customerDF.show()

// drop fully identical rows
val withoutDuplicates = customerDF.dropDuplicates()

println("*** Now without duplicates")

withoutDuplicates.show()

// drop fully identical rows
val withoutPartials = customerDF.dropDuplicates(Seq("name", "state"))

println("*** Now without partial duplicates too")

withoutPartials.show()

 }
 }

答案 5 :(得分:-1)

这是我的Df包含4重复两次,所以这里将删除重复的值。

scala> df.show
+-----+
|value|
+-----+
|    1|
|    4|
|    3|
|    5|
|    4|
|   18|
+-----+

scala> val newdf=df.dropDuplicates

scala> newdf.show
+-----+
|value|
+-----+
|    1|
|    3|
|    5|
|    4|
|   18|
+-----+