如何在 pyspark 中获取 groupBy 之后每个计数的总计百分比?



给定以下数据帧:

import findspark
findspark.init()
from pyspark.sql import SparkSession
spark = SparkSession.builder.master("local").appName("test").getOrCreate()
df = spark.createDataFrame([['a',1],['b', 2],['a', 3]], ['category', 'value'])
df.show()

+--------+-----+
|category|value|
+--------+-----+
|       a|    1|
|       b|    2|
|       a|    3|
+--------+-----+

我想计算每个类别中的项目数量,并为每次计数提供总计的百分比,如下所示

+--------+-----+----------+
|category|count|percentage|
+--------+-----+----------+
|       b|    1|     0.333|
|       a|    2|     0.667|
+--------+-----+----------+

您可以使用以下内容获取总计的计数和百分比/比率

import pyspark.sql.functions as f
from pyspark.sql.window import Window
df.groupBy('category').count()
.withColumn('percentage', f.round(f.col('count') / f.sum('count')
.over(Window.partitionBy()),3)).show()
+--------+-----+----------+
|category|count|percentage|
+--------+-----+----------+
|       b|    1|     0.333|
|       a|    2|     0.667|
+--------+-----+----------+

前面的语句可以分为几个步骤。df.groupBy('category').count()产生count

+--------+-----+
|category|count|
+--------+-----+
|       b|    1|
|       a|    2|
+--------+-----+

然后通过应用窗口函数,我们可以获得每行的总数:

df.groupBy('category').count().withColumn('total', f.sum('count').over(Window.partitionBy())).show()
+--------+-----+-----+
|category|count|total|
+--------+-----+-----+
|       b|    1|    3|
|       a|    2|    3|
+--------+-----+-----+

其中,total列是通过将分区(包含所有行的单个分区(中的所有计数相加来计算的。

一旦我们有了每一行的counttotal,我们就可以计算出比率:

df.groupBy('category')
.count()
.withColumn('total', f.sum('count').over(Window.partitionBy()))
.withColumn('percentage',f.col('count')/f.col('total'))
.show()
+--------+-----+-----+------------------+
|category|count|total|        percentage|
+--------+-----+-----+------------------+
|       b|    1|    3|0.3333333333333333|
|       a|    2|    3|0.6666666666666666|
+--------+-----+-----+------------------+

您可以使用agggroupby和聚合:

import pyspark.sql.functions as F
df.groupby('category').agg(F.count('value') / df.count()).show()

输出:

+--------+------------------+
|category|(count(value) / 3)|
+--------+------------------+
|       b|0.3333333333333333|
|       a|0.6666666666666666|
+--------+------------------+

为了使它更好,您可以使用:

df.groupby('category').agg(
(
F.round(F.count('value') / df.count(), 2)
).alias('ratio')
).show()

输出:

+--------+-----+
|category|ratio|
+--------+-----+
|       b| 0.33|
|       a| 0.67|
+--------+-----+

您还可以使用 SQL:

df.createOrReplaceTempView('df')
spark.sql(
"""
SELECT category, COUNT(*) / (SELECT COUNT(*) FROM df) AS ratio
FROM df
GROUP BY category
"""
).show()

最新更新