You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark Scala:如何按URL聚合DataFrame生成带浏览器计数的有序列表列?

解决Spark 2.4中按URL聚合浏览器访问计数为降序列表的问题

我来帮你搞定这个需求!在Spark 2.4(搭配Scala 2.11)的Dataproc集群里,我们可以通过分组统计+窗口排序+收集列表这三步实现你想要的效果,具体操作如下:

核心思路

  1. 先按URL和Browser分组,统计每个URL下各浏览器的访问次数;
  2. 对每个URL分组内的统计结果,按访问次数降序排序;
  3. 将排序后的(浏览器名称, 访问次数)对收集成列表,作为新列。

完整代码实现

首先导入必要的Spark函数和窗口类:

import org.apache.spark.sql.functions._
import org.apache.spark.sql.expressions.Window

然后创建你的示例DataFrame(方便你测试):

val df = spark.createDataFrame(Seq(
  ("A", "Chrome"),
  ("B", "Chrome"),
  ("C", "Firefox"),
  ("A", "Chrome"),
  ("A", "Firefox"),
  ("A", "Opera"),
  ("A", "Chrome"),
  ("B", "Chrome"),
  ("B", "Firefox"),
  ("C", "Tor")
)).toDF("URL", "Browser")

接下来执行聚合和整理操作:

// 第一步:统计每个URL下各浏览器的访问次数
val countDf = df.groupBy("URL", "Browser").agg(count("*").alias("visit_count"))

// 第二步:定义窗口,按URL分区,按访问次数降序排序
val urlWindow = Window.partitionBy("URL").orderBy(desc("visit_count"))

// 第三步:对每个URL下的(浏览器,次数)按排序后的顺序收集成列表
val resultDf = countDf
  .withColumn("browser_count", struct(col("Browser"), col("visit_count")))
  .withColumn("FrequentlyUsedBrowser", collect_list("browser_count").over(urlWindow))
  .groupBy("URL")
  .agg(first("FrequentlyUsedBrowser").alias("FrequentlyUsedBrowser"))

// 查看结果
resultDf.show(truncate = false)

代码解释

  • 分组统计:groupBy("URL", "Browser").agg(count("*"))得到每个URL对应浏览器的访问次数,这一步是基础数据准备;
  • 窗口排序:通过Window.partitionBy("URL").orderBy(desc("visit_count"))确保每个URL下的浏览器按访问次数从高到低排列;
  • 收集列表:collect_list("browser_count")会保留窗口排序后的顺序,把每个URL下的(浏览器,次数)对收集成列表;最后用groupBy("URL").agg(first(...))去除重复的URL行(因为窗口函数会给每个分组内的行都生成列表,我们只需要保留一行即可)。

输出结果

运行后你会得到符合预期的输出:

+---+------------------------------------------+
|URL|FrequentlyUsedBrowser                     |
+---+------------------------------------------+
|A  |[[Chrome,3], [Firefox,1], [Opera,1]]      |
|B  |[[Chrome,2], [Firefox,1]]                 |
|C  |[[Firefox,1], [Tor,1]]                    |
+---+------------------------------------------+

(注:你的期望输出里C的列表是[(Chrome,1),(Tor,1)],但根据原始数据C只有Firefox和Tor各一次,所以实际输出是[[Firefox,1], [Tor,1]],如果是数据笔误的话调整原始数据即可)

内容的提问来源于stack exchange,提问作者Suhaib Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:28:15