first version of the program

This commit is contained in:
Дмитрий Зязев 2026-04-17 18:07:02 +03:00
parent bfd01ad04b
commit 5d0c1614c8
2 changed files with 140 additions and 21 deletions

8
data/students.csv Normal file
View File

@ -0,0 +1,8 @@
student_id;full_name;group;course;grade;subject
1;Анна Кузнецова;ИВТ-201;2;85;Математика
2;Иван Соколов;ИВТ-201;2;92;Математика
1;Анна Кузнецова;ИВТ-201;2;78;Программирование
3;Мария Ткач;ПИ-101;1;88;Программирование
2;Иван Соколов;ИВТ-201;2;91;Программирование
4;Иван Иванович;ИНБб-2301;3;95;Программирование
4;Иван Иванович;ИНБб-2301;3;91;Математика
1 student_id full_name group course grade subject
2 1 Анна Кузнецова ИВТ-201 2 85 Математика
3 2 Иван Соколов ИВТ-201 2 92 Математика
4 1 Анна Кузнецова ИВТ-201 2 78 Программирование
5 3 Мария Ткач ПИ-101 1 88 Программирование
6 2 Иван Соколов ИВТ-201 2 91 Программирование
7 4 Иван Иванович ИНБб-2301 3 95 Программирование
8 4 Иван Иванович ИНБб-2301 3 91 Математика

View File

@ -1,45 +1,156 @@
import csv
from collections import defaultdict
def load_students(filepath): def load_students(filepath):
records = []
try:
with open(filepath, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f, delimiter=';')
for row in reader:
row['student_id'] = int(row['student_id'])
row['course'] = int(row['course'])
row['grade'] = float(row['grade'])
records.append(row)
except FileNotFoundError:
print(f"Файл {filepath} не найден.")
return records
def filter_by_group(records, group_name): def filter_by_group(records, group_name):
return [r for r in records if r['group'] == group_name]
def filter_by_course(records, course_number): def filter_by_course(records, course_number):
return [r for r in records if r['course'] == course_number]
def filter_by_min_grade(records, min_grade): def filter_by_min_grade(records, min_grade):
return [r for r in records if r['grade'] >= min_grade]
def average_grade_per_student(records): def average_grade_per_student(records):
if not records:
return {}
total_grades = defaultdict(float)
count_grades = defaultdict(int)
names = {}
for r in records:
sid = r['student_id']
total_grades[sid] += r['grade']
count_grades[sid] += 1
names[sid] = r['full_name']
result = {}
for sid in total_grades:
result[sid] = {
'name': names[sid],
'avg_grade': total_grades[sid] / count_grades[sid]
}
return result
def top_students_by_avg(records, n): def top_students_by_avg(records, n):
avg_dict = average_grade_per_student(records)
if not avg_dict:
return []
students = [(sid, data['name'], data['avg_grade']) for sid, data in avg_dict.items()]
students.sort(key=lambda x: x[2], reverse=True)
return students[:n]
def subject_statistics(records): def subject_statistics(records):
if not records:
return {}
total = defaultdict(float)
count = defaultdict(int)
for r in records:
subj = r['subject']
total[subj] += r['grade']
count[subj] += 1
stats = {}
for subj in total:
stats[subj] = {'count': count[subj], 'avg': total[subj] / count[subj]}
return stats
def grade_distribution(records, subject=None): def grade_distribution(records, subject=None):
def to_five_point(grade):
if grade < 60:
return 2
elif grade < 75:
return 3
elif grade < 90:
return 4
else:
return 5
filtered = records
if subject is not None:
filtered = [r for r in records if r['subject'] == subject]
dist = {2: 0, 3: 0, 4: 0, 5: 0}
for r in filtered:
dist[to_five_point(r['grade'])] += 1
return dist
def remove_duplicate_records(records): def remove_duplicate_records(records):
seen = set()
unique = []
for r in records:
key = (r['student_id'], r['subject'], r['grade'])
if key not in seen:
seen.add(key)
unique.append(r)
return unique
def export_grade_report(records, filtered, output_file):
with open(output_file, 'w', encoding='utf-8') as f:
def export_grade_report(records, output_file): f.write(f"Загружено записей: {len(records)}\n")
f.write(f"После удаления дубликатов: {len(records)}\n")
f.write(f"После фильтрации (курс 2, оценка >= 80): {len(filtered)} записей\n")
if filtered:
overall_avg_filtered = sum(r['grade'] for r in filtered) / len(filtered)
f.write(f"Средний балл по выборке: {overall_avg_filtered:.2f}\n")
else:
f.write("Средний балл по выборке: нет данных\n")
top3 = top_students_by_avg(filtered, 3)
f.write("Топ-3 студента:\n")
i = 1
for sid, name, avg in top3:
f.write(f" {i}. {name} - {avg:.2f}")
i += 1
dist = grade_distribution(filtered)
f.write("Распределение оценок:\n")
f.write(f" 5 (90-100): {dist[5]}\n")
f.write(f" 4 (75-89): {dist[4]}\n")
f.write(f" 3 (60-74): {dist[3]}\n")
f.write(f" 2 (0-59): {dist[2]}\n")
subj_stats = subject_statistics(filtered)
f.write("Статистика по предметам:\n")
for subj, data in subj_stats.items():
f.write(f" {subj}: оценок {data['count']}, средний {data['avg']:.2f}\n")
def main(): def main():
records = load_students('data/students.csv')
print(f"Загружено записей: {len(records)}")
records = remove_duplicate_records(records)
print(f"После удаления дубликатов: {len(records)}")
filtered = filter_by_course(records, 2)
filtered = filter_by_min_grade(filtered, 80)
print(f"После фильтрации (курс 2, оценка >= 80): {len(filtered)} записей")
if filtered:
overall_avg_filtered = sum(r['grade'] for r in filtered) / len(filtered)
print(f"Средний балл по выборке: {overall_avg_filtered:.2f}")
else:
print("Средний балл по выборке: нет данных")
top3 = top_students_by_avg(filtered, 3)
print("Топ-3 студента:")
i = 1
for sid, name, avg in top3:
print(f" {i}. {name} - {avg:.2f}")
i += 1
dist = grade_distribution(filtered)
print("Распределение оценок:")
print(f" 5 (90-100): {dist[5]}")
print(f" 4 (75-89): {dist[4]}")
print(f" 3 (60-74): {dist[3]}")
print(f" 2 (0-59): {dist[2]}")
subj_stats = subject_statistics(filtered)
print("Статистика по предметам:")
for subj, data in subj_stats.items():
print(f" {subj}: оценок {data['count']}, средний {data['avg']:.2f}")
export_grade_report(records, filtered, 'output.txt')
print("Полный отчёт сохранён в output.txt")
if __name__ == '__main__': if __name__ == '__main__':
main() main()