PySpark - 获取重复行的索引

时间:2018-06-14 20:55:34

标签: python apache-spark pyspark

假设我有一个PySpark数据框,如下所示:

+--+--+--+--+
|a |b |c |d |
+--+--+--+--+
|1 |0 |1 |2 |
|0 |2 |0 |1 |
|1 |0 |1 |2 |
|0 |4 |3 |1 |
+--+--+--+--+

如何创建标记所有重复行的列,如下所示:

+--+--+--+--+--+
|a |b |c |d |e |
+--+--+--+--+--+
|1 |0 |1 |2 |1 |
|0 |2 |0 |1 |0 |
|1 |0 |1 |2 |1 |
|0 |4 |3 |1 |0 |
+--+--+--+--+--+

我尝试使用groupBy和聚合函数无效。

4 个答案:

答案 0 :(得分:2)

定义window函数以检查按所有列分组时行的count是否大于1.如果是,则重复(1)否则不重复(0)

allColumns = df.columns
import sys
from pyspark.sql import functions as f
from pyspark.sql import window as w
windowSpec = w.Window.partitionBy(allColumns).rowsBetween(-sys.maxint, sys.maxint)

df.withColumn('e', f.when(f.count(f.col('d')).over(windowSpec) > 1, f.lit(1)).otherwise(f.lit(0))).show(truncate=False) 

应该给你

+---+---+---+---+---+
|a  |b  |c  |d  |e  |
+---+---+---+---+---+
|1  |0  |1  |2  |1  |
|1  |0  |1  |2  |1  |
|0  |2  |0  |1  |0  |
|0  |4  |3  |1  |0  |
+---+---+---+---+---+

我希望答案很有帮助

<强>更新

作为@pault commented,您可以通过将when转换为col来消除litbooleaninteger

df.withColumn('e', (f.count('*').over(windowSpec) > 1).cast('int')).show(truncate=False)

答案 1 :(得分:2)

只是扩展my comment

您可以按所有列进行分组,并使用pyspark.sql.functions.count()确定列是否重复:

import pyspark.sql.functions as f
df.groupBy(df.columns).agg((f.count("*")>1).cast("int").alias("e")).show()
#+---+---+---+---+---+
#|  a|  b|  c|  d|  e|
#+---+---+---+---+---+
#|  1|  0|  1|  2|  1|
#|  0|  2|  0|  1|  0|
#|  0|  4|  3|  1|  0|
#+---+---+---+---+---+

这里我们使用count("*") > 1作为聚合函数,并将结果转换为intgroupBy()将导致删除重复的行。根据您的需要,这可能就足够了。

但是,如果您想保留所有行,可以使用其他答案中显示的Window函数,也可以使用join()

df.join(
    df.groupBy(df.columns).agg((f.count("*")>1).cast("int").alias("e")),
    on=df.columns,
    how="inner"
).show()
#+---+---+---+---+---+
#|  a|  b|  c|  d|  e|
#+---+---+---+---+---+
#|  1|  0|  1|  2|  1|
#|  1|  0|  1|  2|  1|
#|  0|  2|  0|  1|  0|
#|  0|  4|  3|  1|  0|
#+---+---+---+---+---+

在这里,我们将原始数据框与所有列上方groupBy()的结果相连接。

答案 2 :(得分:1)

使用所有列对数据帧进行分区,然后应用dense_rank。

import sys
from pyspark.sql.functions import dense_rank
from pyspark.sql import window as w

df.withColumn('e', dense_rank().over(w.Window.partitionBy(df.columns))).show()

答案 3 :(得分:0)

df1=df_interr.groupBy("Item_group","Item_name","price").count().filter("count > 1")