题目
使用Spark DataFrame计算每个部门的平均工资
信息
- 类型:问答
- 难度:⭐
考点
DataFrame API, 聚合操作, 分组操作
快速回答
使用Spark DataFrame的groupBy()和agg()方法实现:
- 按部门分组数据
- 使用
avg()函数计算平均工资 - 可选:使用
withColumnRenamed()重命名结果列
示例代码:df.groupBy("department").agg(avg("salary").alias("avg_salary"))
解析
问题场景
假设有一个包含员工信息的DataFrame,包含name(姓名)、department(部门)和salary(工资)三列。需要计算每个部门的平均工资。
核心原理
Spark DataFrame的聚合操作分为两步:
- 分组:使用
groupBy()按指定列(此处为部门)分组数据 - 聚合:使用
agg()配合聚合函数(如avg())计算汇总值
Spark会在集群上并行执行这些操作,自动优化执行计划。
代码实现
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions.avg
// 创建SparkSession
val spark = SparkSession.builder().appName("DepartmentAvgSalary").getOrCreate()
// 示例数据(实际中通常从文件/数据库读取)
val data = Seq(
("Alice", "HR", 5000),
("Bob", "Engineering", 7000),
("Charlie", "Engineering", 8000),
("David", "HR", 4500)
)
val df = spark.createDataFrame(data).toDF("name", "department", "salary")
// 核心计算:按部门分组并计算平均工资
val result = df.groupBy("department")
.agg(avg("salary").alias("avg_salary"))
// 显示结果
result.show()
/* 输出示例:
+------------+----------+
| department|avg_salary|
+------------+----------+
| HR| 4750.0|
|Engineering | 7500.0|
+------------+----------+ */最佳实践
- 列别名:使用
alias()或as()给聚合结果列命名(如alias("avg_salary")),避免自动生成的列名如avg(salary) - 导入函数:显式导入聚合函数(
import org.apache.spark.sql.functions.avg),避免使用字符串表达式 - 数据类型:注意数值类型处理,
avg()默认返回Double类型
常见错误
- 错误1:忘记导入聚合函数导致编译错误
解决:添加import org.apache.spark.sql.functions._或具体函数 - 错误2:拼写错误(如
groupby小写)
解决:Scala区分大小写,正确使用groupBy - 错误3:对非数值列使用
avg()
解决:确保目标列是数值类型(Integer/Double等)
扩展知识
- 多列聚合:可在
agg()中同时计算多个指标df.groupBy("department").agg(avg("salary"), max("salary")) - SQL语法:也可用Spark SQL实现
spark.sql("SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department") - 性能优化:当分组列基数大时,可调整
spark.sql.shuffle.partitions参数控制并行度