题目要求为(对应任务文件为:test1、test2....): (1)Tom 同学的总成绩平均分是多少; (2)Mary 选了多少门课; (3)各门课程的平均分是多少; (4)该系 DataBase 课程共有多少人选修; (5)列出及格(分数大于 60)的学生、课程及成绩
时间: 2025-08-19 12:16:59 浏览: 2
<think>好的,用户希望根据给定的学生成绩数据计算五个统计指标,包括平均分、选课数量、课程平均分、选修人数和及格学生列表。用户之前已经提供了一个Scala和Spark的实现方案,现在需要根据新的引用内容进行调整,同时参考之前的回答。
首先,我需要确认用户的需求是否有所变化。根据引用[1],用户可能需要处理班级信息,但当前的问题中并没有提到班级,可能需要忽略这部分,或者确认是否需要整合班级信息。但用户的问题里主要关注的是Tom、Mary、各课程平均分等,所以可能不需要处理班级。
引用[2]提到每个文件代表一个学科的成绩,每行是学生名字和成绩,要求计算平均成绩并输出到新文件。这可能与用户的问题中的数据结构不同,用户的数据结构是每个记录包含姓名、课程、成绩,即三个字段。所以需要确保数据读取部分正确。
接下来,用户的问题中的五个需求与之前的Scala实现一致,因此需要检查之前的代码是否符合新的引用中的要求。例如,编程要求中可能需要补充代码,但用户的问题更偏向于如何实现这些统计。
需要注意的点:
1. Tom的平均分:使用filter筛选Tom的记录,然后计算平均分。可能需要处理可能的空值,但用户的问题中没有提到缺失值,所以暂时可以忽略。
2. Mary的选课数:同样使用filter和count。
3. 各课程平均分:按课程分组,计算平均分,可能需要四舍五入。
4. Database课程的人数:需要distinct学生姓名,避免重复计算同一学生多次选修同一课程。
5. 及格学生列表:分数>=60,并显示所有及格记录,按学生和课程排序。
需要确保Spark会话正确创建,数据读取的路径正确,schema定义正确,尤其是字段类型是否匹配。例如,成绩应该是Double类型。
另外,根据引用[1],用户可能需要处理班级信息,但当前的问题中没有提到,所以可能不需要。但如果有班级字段,可能需要调整schema,但根据用户提供的代码,原始数据是name, course, score三个字段,所以可能不需要处理班级。
在实现说明中,需要解释每个步骤的关键点,比如使用agg函数、count、groupBy等。同时,代码特性需要强调排序、格式化和去重。
最后,生成相关问题需要考虑用户可能遇到的后续问题,如处理缺失值、输出格式、性能优化等,与之前的回答保持一致。</think>根据需求,以下是基于Spark的完整实现方案,包含中文注释说明和代码规范:
```scala
import org.apache.spark.sql.{SparkSession, functions => F}
object StudentStatistics {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder()
.appName("StudentScoreAnalysis")
.master("local[*]")
.getOrCreate()
// 假设数据格式:姓名,课程,成绩(例如:Tom,Math,85.0)
val df = spark.read
.option("header", "true")
.schema("name STRING, course STRING, score DOUBLE")
.csv("/path/to/score_data.csv")
// 1. 计算Tom的总成绩平均分
df.filter(F.col("name") === "Tom")
.agg(F.avg("score").alias("Tom平均分"))
.show()
// 2. 统计Mary选课数量
println("Mary选课总数: " +
df.filter(F.col("name") === "Mary").count())
// 3. 计算各课程平均分(保留两位小数)
df.groupBy("course")
.agg(F.round(F.avg("score"), 2).alias("课程平均分"))
.orderBy("course")
.show()
// 4. 统计选修Database课程的人数(去重计数)
println("选修Database人数: " +
df.filter(F.col("course") === "Database")
.select("name").distinct().count())
// 5. 列出所有及格学生记录(分数>=60)
df.filter(F.col("score") >= 60)
.select("name", "course", "score")
.orderBy(F.col("name"), F.col("course"))
.show()
spark.stop()
}
}
```
### 关键实现解析
1. **数据加载**
使用`spark.read.schema`明确指定数据结构,避免类型推断错误[^1]。CSV文件需包含表头,若原始数据无表头需设置`.option("header", "false")`
2. **Tom平均分计算**
- `filter`筛选特定学生
- `agg(avg(...))`聚合计算平均值[^2]
- 处理空值情况:当Tom无成绩记录时会返回null,可添加`.na.fill(0)`处理
3. **Mary选课统计**
- `count()`在过滤后直接统计记录数
- 若需排除重复课程,可结合`distinct().count()`
4. **课程平均分计算**
- `groupBy`按课程分组
- `round(...,2)`规范数值显示格式[^3]
- `orderBy`保证结果有序输出
5. **Database选课人数**
- `distinct()`确保学生不重复计数
- 若允许同学生多次选修,可移除`distinct()`
6. **及格记录筛选**
- 使用`>= 60`进行条件过滤
- `orderBy`按姓名和课程排序输出
- 可添加`.coalesce(1)`合并结果到单个文件保存
### 性能优化建议
1. 对`name`和`course`字段建立索引可提升过滤效率[^4]
2. 使用`cache()`缓存多次使用的DataFrame
3. 通过`repartition`优化数据分布,如按课程字段分区
阅读全文
相关推荐















