答案 0 :(得分:0)
DataFrame中的null
值导致聚合问题。一种选择是将这些值替换为非null的值,以便进行聚合。
例如:
new_df = test_df.withColumn(
"Country",
F.when(
F.isnull("Country"),
"None"
).otherwise(F.col("Country"))
)
这将返回一个DataFrame,其中null
列的Country
值已替换为字符串"None"
。 (我故意避免使用字符串"null"
来避免歧义。)
现在,您可以使用pyspark.sql.functions.rank()
和pyspark.sql.Window
按频率计算每个国家/地区的排名并对其进行排名。
from pyspark.sql import Window
new_df.groupBy("Country")\
.agg(
F.count("Country").alias("Count"),
F.rank().over(Window.orderBy(F.count("Country").desc())).alias("Rank")
)\
.show()
#+-------+-----+----+
#|Country|Count|Rank|
#+-------+-----+----+
#| USA| 4| 1|
#| None| 2| 2|
#| MEX| 1| 3|
#| | 1| 3|
#| DEU| 1| 3|
#| CAN| 1| 3|
#+-------+-----+----+
如您所见,由于替换,"None"
显示在县列中。此时,您拥有计算所需聚合所需的一切。
count
)只是Count
列的总和。distinct_country
)的计算方式类似于您在帖子中的操作方式。pyspark.sql.functions.collect_list()
计算最终输出列(top_2_countries
),过滤rank <= 2
的值。例如:
new_df.groupBy("Country")\
.agg(
F.count("Country").alias("Count"),
F.rank().over(Window.orderBy(F.count("Country").desc())).alias("Rank")
)\
.agg(
F.sum("Count").alias("count"),
F.countDistinct("Country").alias("distinct_country"),
F.collect_list(F.when(F.col("rank")<=2, F.col("Country"))).alias("top_2_countries")
)\
.show()
#+-----+----------------+---------------+
#|count|distinct_country|top_2_countries|
#+-----+----------------+---------------+
#| 10| 6| [USA, None]|
#+-----+----------------+---------------+
请注意这里的两件事。首先,计数是6而不是你的例子中的5。 5是null
中countDistinct()
被忽略的结果。同样,top_2_countries
列的值为[USA, None]
。
出于演示目的,如果您已将"None"
值转换回null
,将会发生以下情况:
new_df.groupBy("Country")\
.agg(
F.count("Country").alias("Count"),
F.rank().over(Window.orderBy(F.count("Country").desc())).alias("Rank")
)\
.withColumn(
"Country",
F.when(F.col("Country") == "None", None).otherwise(F.col("Country"))
)\
.agg(
F.sum("Count").alias("count"),
F.countDistinct("Country").alias("distinct_country"),
F.collect_list(F.when(F.col("rank")<=2, F.col("Country"))).alias("top_2_countries")
)\
.show()
#+-----+----------------+---------------+
#|count|distinct_country|top_2_countries|
#+-----+----------------+---------------+
#| 10| 5| [USA]|
#+-----+----------------+---------------+
正如您所看到的那样,非重复计数为5,但top_2_countries
列不包含null
。这是因为null
被排除在collect_list()
1 之外。 (见this example)。
1 请务必注意,我在调用collect_list()
时利用了这一事实。来自pyspark.sql.functions.when()
的文档:
如果未调用Column.otherwise(),则为不匹配的条件返回None。