Dataframe PySpark重新分配重复行的值

Dataframe PySpark重新分配重复行的值,dataframe,pyspark,duplicates,python-3.7,Dataframe,Pyspark,Duplicates,Python 3.7,我有这样一个数据帧: id,p1 1,A 2,null 3,B 4,null 4,null 2,C 使用PySpark,我想删除所有重复项。但是,如果存在p1列不为null的副本,我希望删除null列。例如,我想删除第一个出现的id 2和id 4。现在,我将数据帧拆分为两个数据帧: id,p1 1,A 3,B 2,C 从两个数据帧中删除重复项,然后添加不在第一个数据帧中的重复项。这样我就得到了这个数据帧 id,p1 1,A 3,B 4,null 2,C 这就是我到目前为止所做的: from

我有这样一个数据帧:

id,p1
1,A
2,null
3,B
4,null
4,null
2,C
使用PySpark,我想删除所有重复项。但是,如果存在p1列不为null的副本,我希望删除null列。例如,我想删除第一个出现的id 2和id 4。现在,我将数据帧拆分为两个数据帧:

id,p1
1,A
3,B
2,C
从两个数据帧中删除重复项,然后添加不在第一个数据帧中的重复项。这样我就得到了这个数据帧

id,p1
1,A
3,B
4,null
2,C
这就是我到目前为止所做的:

from pyspark.sql import SparkSession

spark = SparkSession.builder.appName('test').getOrCreate()
d = spark.createDataFrame(
    [(1,"A"),
     (2,None),
     (3,"B"),
     (4,None),
     (4,None),
     (2,"C")],
    ["id", "p"]
    )
d1 = d.filter(d.p.isNull())
d2 = d.filter(d.p.isNotNull())
d1 = d1.dropDuplicates()
d2 = d2.dropDuplicates()
d3 = d1.join(d2, "id", 'left_anti')
d4 = d2.unionByName(d3)

有没有更漂亮的方法?这种感觉真的很多余,但我想不出更好的办法了。我尝试使用groupby,但没有成功。有什么想法吗?谢谢。

使用window
行号()
函数和
“p”
降序进行排序

(df1.sort(col('p1').desc())#sort column descending and will put nulls low in list
 
.dropDuplicates(subset = ['id']).show()#Drop duplicates on column id
)

+---+----+
| id|  p1|
+---+----+
|  1|   A|
|  2|   C|
|  3|   B|
|  4|null|
+---+----+
示例:

d.show()
#+---+----+
#| id|   p|
#+---+----+
#|  1|   A|
#|  2|null|
#|  3|   B|
#|  4|null|
#|  4|null|
#|  2|   C|
#+---+----+

from pyspark.sql.functions import col, row_number
from pyspark.sql.window import Window

window_spec=row_number().over(Window.partitionBy("id").orderBy(col("p").desc()))

d.withColumn("rn",window_spec).filter(col("rn")==1).drop("rn").show()
#+---+----+
#| id|   p|
#+---+----+
#|  1|   A|
#|  3|   B|
#|  2|   C|
#|  4|null|
#+---+----+

I get
“Column”对象不可调用
。但肯定会继续学习如何使用行号和窗口。谢谢@mnsr,确保您关闭了所有括号,我能够执行上述代码而没有任何问题!事实上,你是对的!我的错。非常感谢你。
d.show()
#+---+----+
#| id|   p|
#+---+----+
#|  1|   A|
#|  2|null|
#|  3|   B|
#|  4|null|
#|  4|null|
#|  2|   C|
#+---+----+

from pyspark.sql.functions import col, row_number
from pyspark.sql.window import Window

window_spec=row_number().over(Window.partitionBy("id").orderBy(col("p").desc()))

d.withColumn("rn",window_spec).filter(col("rn")==1).drop("rn").show()
#+---+----+
#| id|   p|
#+---+----+
#|  1|   A|
#|  3|   B|
#|  2|   C|
#|  4|null|
#+---+----+