Last active
December 15, 2023 18:30
-
-
Save reagle/9cc2f4e2f98446528128d1f6edfe3d73 to your computer and use it in GitHub Desktop.
Using dictionary of letter grades, calculate mean GPA from list of letter grades converted to points
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
"""Using dictionary of letter grades, calculate mean GPA from list | |
of letter grades converted to points""" | |
# https://gist.github.com/reagle/9cc2f4e2f98446528128d1f6edfe3d73 | |
# add results to e-statement-1b-teaching-trace-table.xlsx | |
__author__ = "Joseph Reagle" | |
__copyright__ = "Copyright (C) 2021-2024 Joseph Reagle" | |
__license__ = "GLPv3" | |
__version__ = "1.1" | |
import statistics | |
from collections import Counter | |
try: | |
import asciietch.graph as ag # type:ignore | |
asciietch_imported = True | |
except ImportError: | |
asciietch_imported = False | |
print("`pip install asciietch` if you want nice graphs ▁▅█▂▁▃▁▂▁▁▁▂▁") | |
print(" https://github.com/linkedin/asciietch\n") | |
# https://registrar.northeastern.edu/article/how-to-calculate-your-gpa/ | |
POINTS = { | |
"A+": 4.0, | |
"A": 4.0, | |
"A-": 3.667, | |
"B+": 3.333, | |
"B": 3.0, | |
"B-": 2.667, | |
"C+": 2.333, | |
"C": 2.0, | |
"C-": 1.667, | |
"D+": 1.333, | |
"D": 1.0, | |
"D-": 0.667, | |
"F": 0, | |
} | |
def calc_gpa(grades: list[str]) -> float: | |
"""Calculate mean GPA from list of letter grades converted to points.""" | |
return statistics.mean([POINTS[grade] for grade in grades]) | |
def print_header(): | |
"""Print a header for the output.""" | |
print(f"{'COURSE':<15} {'N':<5} {'MEAN':<10}", end="") | |
print(" ".join(f"{letter:<2}" for letter in POINTS.keys())) | |
def print_course(title: str, grades: list[str]) -> None: | |
"""Print single-line information for a course.""" | |
print(f"{title:<15} N={len(grades):02d} μ={calc_gpa(grades):.2f}", end=" ") | |
distribution = [grades.count(letter) for letter in POINTS] | |
counter = Counter(grades) | |
for letter in POINTS.keys(): | |
if letter in counter: | |
print(f"{counter[letter]:<3}", end="") | |
else: | |
print(" ", end="") | |
if asciietch_imported: | |
grapher = ag.Grapher() | |
print(grapher.asciihist(distribution), end="") | |
print() | |
COURSES = { # Target: B+ / 3.33 average | |
################### 2023 Fall | |
# 3.35 unprecedented drops at start, leaving mostly strong students | |
"2023_CDA_2FA": "A- A A- B- A- A- A- C A A A- A A- D- A B- A- A- B- B+", | |
# 3.33 first time teaching public speaking (includes F no show; 3.52 without him) | |
"2023_PS_2_FA": "B+ A- B A- A A- B- A B A- B+ A- A- A F B+ A A- B", | |
################### 2023 Spring | |
# 3.31 | |
"2023_CDA_1_SP": ( | |
"B B A A- A A- A- A- B+ A- A- A- A- A- A- F A B B+ A F A C+ A- A A A- B+ A- C+" | |
), | |
# 3.60, excellent students | |
"2023_OC_1_SP": "B+ A A B- B+ A- A- A A A- B A A B", | |
################### 2022 Fall | |
# 3.44 | |
"2022_CDA_2FA": ( | |
"D+ A A B+ A- A- A- A B+ B+ A- A- A A- A- B+ A A B+ B B B+ A- B B B+ A C+" | |
), | |
# 3.48 | |
"2022_OC_2FA": "A- A B+ A C B+ B+ A- A", | |
################### 2022 Spring | |
# 3.42 | |
"2022_CDA_1_SP": ( | |
"C- A- A A- C- B A- A- A- B+ A B+ B+ A B+ B A- A- A A B+ A A- B A- B+ B" | |
), | |
# 3.61, excellent students | |
"2022_PC_1_SP": "B+ B+ A A- B+ B+ A B A- A A- A A A- A- A- B", | |
# "TEST": "A B B C C C D D D D F F F F F", | |
} | |
print_header() | |
for title, grades in COURSES.items(): | |
print_course(title, grades.split(" ")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment