使用Scala编写确定性代码,按Artist分组获取最频繁Skill生成DataFrame
Scala Spark: 获取每个艺术家最常用的技能
嘿,这里有个完全确定性的Scala解决方案,基于Spark DataFrame API实现你的需求——让每个艺术家单独占一行,显示他们出现次数最多的技能。如果遇到多个技能次数相同的情况,我们还会通过技能名称排序来保证结果稳定,不会随机输出。
假设你已经有了一个名为inputDF的DataFrame,结构包含Artist(String类型)和Skill(String类型)字段,直接用下面的代码就能搞定:
import org.apache.spark.sql.functions._ import org.apache.spark.sql.expressions.Window // 第一步:统计每个艺术家每种技能的出现次数 val skillCountDF = inputDF .groupBy("Artist", "Skill") .agg(count("*").alias("skill_count")) // 第二步:定义窗口规则——按艺术家分组,先按次数降序,再按技能名升序(确保确定性) val artistWindow = Window .partitionBy("Artist") .orderBy(desc("skill_count"), asc("Skill")) // 第三步:给每个分组内的记录排名,取排名第一的就是最常用技能 val resultDF = skillCountDF .withColumn("rank", row_number().over(artistWindow)) .filter(col("rank") === 1) .select("Artist", "Skill") .withColumnRenamed("Skill", "Most Common Skill") // 输出结果看看 resultDF.show()
代码逻辑说明
- 统计频次:先通过
groupBy+count拿到每个艺术家-技能组合的出现次数,这是后续计算的基础数据。 - 窗口函数保障确定性:用
Window.partitionBy("Artist")把数据按艺术家拆分,排序规则优先看技能次数(降序),次数相同的话按技能名称升序排列——这一步是核心,能避免多个技能次数相同时结果随机的问题,完全满足你要的「确定性代码」要求。 - 筛选Top1技能:
row_number()会给每个分组内的记录按排序规则编号,过滤出编号为1的行就是我们要的最常用技能,最后重命名列就得到你想要的输出格式。
测试示例数据
如果用你给出的15行输入数据运行这段代码,输出会和预期完全一致:
+-------+----------------+ | Artist|Most Common Skill| +-------+----------------+ | Bono| Vocals| | Edge| Guitar| | Larry| Drum| |Clayton| Bass| +-------+----------------+
内容的提问来源于stack exchange,提问作者mike_di
相关产品推荐
相关产品推荐

