基于条件的数据框聚合 (Pyspark)

Aggregation of a data frame based on condition (Pyspark)

我需要以下任务的帮助:
我获得了一个 groupby 结果,其中我有一个包含多个地址的列表(这里只是一个地址的剪切),其中有人占用了这些地址。我需要计算该应用程序的使用率,以便除以 [name] + Active Count / [name] + Passive Count 并使用 [address][name][usage_ratio]

我从来没有做过类似的聚合,我不知道从哪里开始或如何循环执行它。有人可以帮忙吗?

+------------+--------------------+----------------+-----+
|     address|                name|      use_of_app|count|
+------------+--------------------+----------------+-----+
|          33|                Mark|          active|   35|
|          33|                Mark|         passive|    4|
|          33|               Abbie|          active|   30|
|          33|               Abbie|         passive|    2|
|          33|                Anna|         passive|    3|
|          33|                Anna|          active|   32|
|          33|                 Tom|         passive|   38|
|          33|                 Tom|          active|   50|
|          33|             Patrick|         passive|   40|
|          33|             Patrick|          active|   57|
+------------+--------------------+----------------+-----+

我找到了一个可行的解决方案,但它确实占用大量资源且耗时,因此我邀请大家使用 post 更快的工作解决方案。所以我的解决方案是采用上面的数据框,通过 .filter(use_of_app) 将其拆分为两个单独的 activeDF 和 passiveDF,然后根据 name = name 条件将它们重新组合在一起,并将 count(activeDF) 除以 count(activeDF)计数(被动DF)

这是我的代码 - 我在 count 列上使用 sum,因为我不确定每个 use_of_app 有多少行:

from pyspark.sql import functions as F

df = df.groupBy("address", "name").agg(
    (
        F.sum(F.when(F.col("use_of_app") == "active", F.col("count")))
        / F.sum(F.when(F.col("use_of_app") == "passive", F.col("count")))
    ).alias("usage_ratio")
)

df.show()
+-------+-------+------------------+
|address|   name|       usage_ratio|
+-------+-------+------------------+
|     33|  Abbie|              15.0|
|     33|   Mark|              8.75|
|     33|    Tom|1.3157894736842106|
|     33|   Anna|10.666666666666666|
|     33|Patrick|             1.425|
+-------+-------+------------------+

另一种选择是 pivot 步:

from pyspark.sql import function as F

(
    df.groupby("address", "name")
    .pivot("use_of_app", values=["active", "passive"])
    .agg(F.sum("count"))
    .withColumn("ratio", F.col("active") / F.col("passive"))
    .show()
)
# Output
+-------+-----+------+-------+------------------+
|address| name|active|passive|             ratio|
+-------+-----+------+-------+------------------+
|     33|Abbie|    30|      2|              15.0|
|     33| Anna|    32|      3|10.666666666666666|
|     33| Mark|    35|      4|              8.75|
+-------+-----+------+-------+------------------+

+++ 根据史蒂文的建议更新:.pivot("use_of_app", values=["active", "passive"]).