Gradebook et al.

class gradelib.Gradebook(points_earned: DataFrame, points_possible: Series, lateness: DataFrame | None = None, dropped: DataFrame | None = None, notes: Mapping[Student, Mapping[str, Sequence[str]]] | None = None, grading_groups: Mapping[str, float | Tuple[Sequence[str], float] | Tuple[Mapping[str, float], float] | GradingGroup] | None = None, scale: Mapping | None = None, options: GradebookOptions | None = None)

Stores the grades for a class.

Typically a Gradebook is not created manually, but is instead produced by reading grades exported from Gradescope or Canvas, using gradelib.io.gradescope.read() or gradelib.io.canvas.read().

Parameters:
  • points_earned (pandas.DataFrame) – A dataframe with one row per student, and one column for each assignment. Each entry should be the raw number of points earned by the student on the given assignment (or NaN if the student did not turn in the assignment). The index of the dataframe should consist of Student objects.

  • points_possible (pandas.Series) – A series containing the maximum number of points possible for each assignment. The index of the series should match the columns of the points_earned dataframe.

  • lateness (Optional[pandas.DataFrame]) – A dataframe of pd.Timedelta objects with the same columns/index as points_earned. An entry in the dataframe records how late a student turned in the assignment. If None is passed, a dataframe of zero second timedeltas is used by default, effectively indicating that no assignments were late.

  • dropped (Optional[pandas.DataFrame]) – A Boolean dataframe with the same columns/index as points_earned. An entry that is True indicates that the assignment should be dropped. If None is passed, a dataframe of all False is used by default.

  • notes (Optional[Mapping[Student, Mapping[str, Sequence[str]]]]) – A nested dictionary of notes, possibly used by report generating code. The keys of the outer dictionary should be Student objects, and the values should be dictionaries. The keys of the inner dictionary should specify a note channel, and can be either “late”, “drop”, or “misc”; these are signals to reporting code that help determine where to display notes. The values of the inner dictionary should be sequences of strings, each one a message.

  • options (Optional[GradebookOptions]) – Options controlling the behavior of the Gradebook. If not provided, default options are used.

  • grading_groups (Mapping[str, GradingGroup]) –

    A mapping from assignment group names (strings) to GradingGroup objects representing a group of assignments. The default is simply {}.

    To prevent unintentional errors, the grading groups must be set before accessing summative attributes, such as overall_score.

    While the dictionary returned by this attribute has GradingGroup instances as values, the attribute can be set in several ways. See the documentation for the setter for more details.

  • scale (Optional[Mapping]) – An ordered mapping from letter grades to score thresholds used to determine overall letter grades. If not provided, gradelib.scales.DEFAULT_SCALE is used.

notes

A nested dictionary of notes, possibly used by report generating code.

Type:

dict[Student, dict[str, list[str]]]

options

Options controlling the behavior of the Gradebook.

Type:

GradebookOptions

scale

An ordered mapping from letter grades to score thresholds used to determine overall letter grades.

Type:

dict

add_assignment(name: str, points_earned: Series, points_possible: float | int, lateness: Series | None = None, dropped: Series | None = None)

Adds a single assignment to the gradebook, mutating it.

Usually gradebooks do not need to have individual assignments added to them. Instead, gradebooks are read from Canvas, Gradescope, etc. In some instances, though, it can be useful to manually add an assignment to a gradebook – this method makes it easy to do so.

Parameters:
  • name (str) – The name of the new assignment. Must be unique.

  • points_earned (Series[float]) – A Series of points earned by each student.

  • points_possible (float) – The maximum number of points possible on the assignment.

  • lateness (Series[pd.Timedelta]) – How late each student turned in the assignment. Turning in the assignment on time should be represented by a pd.Timedelta of zero seconds. Default: all zero seconds.

  • dropped (Series[bool]) – Whether the assignment should be dropped for any given student. Default: all False.

Raises:

ValueError – If an assignment with the given name already exists, or if grades for a student are missing / grades for an unknown student are provided.

add_note(student: Student, channel: str, message: str)

Add a grading note.

Mutates the gradebook.

Parameters:
  • student (Student) – The student for which the note should be added.

  • channel (str) –

    The channel that the note should be added to. Valid channels are:
    • lates

    • drops

    • attempts

    • misc

  • message (str) – The note’s message.

property assignments: Assignments

All assignments in the gradebook.

This is a derived attribute; it should not be modified.

Return type:

Assignments

property attempted: DataFrame

A table of whether each assignment was attempted (i.e., turned in).

Produces a DataFrame with a row for each student and a column for each assignment. Each entry is True if the student attempted the assignment and False otherwise. An assignment is considered “attempted” if points_earned is not NaN.

copy() Gradebook

Copy the gradebook.

Returns:

A new gradebook with all attributes copied.

Return type:

Gradebook

property grading_group_scores: DataFrame

A table of the scores earned in each grading group.

Produces a DataFrame with a row for each student and a column for each grading group in which each entry is the student’s score within that grading group.

This takes into account dropped assignments.

If an assignment has a score of NaN, it is treated as a zero for the purposes of computing the grading group score. Conceptually, an individual assignment may not be attempted by a student, but a grading group score is always “attempted” and so it cannot be NaN.

If grading_groups has not yet been set, all entries are NaN.

This is a derived attribute; it should not be modified.

property grading_groups: dict[str, GradingGroup]

A grouping of assignments and their weight in the overall grade.

This attribute should be set directly. The value should be a dict mapping group names to grading group definitions. A group definition can be any of the following:

  • A single number. In this case, the group name is treated as an assignment name.

  • A tuple of the form (assignments, group_weight), where assignments is an iterable of assignment names or a dict mapping assignment names to weights. If assignments is an iterable, the weights are inferred to be proportional to the points possible for each assignment. If assignments is a dict, the weights are taken directly from the dict.

  • A GradingGroup instance.

To normalize the weights of assignments (so that they are all weighed the same) use the gradelib.normalize() function.

Example

>>> gradebook.grading_groups = {
...     # list of assignments, followed by group weight. assignment weights
...     # are inferred to be proportional to points possible
...     "homeworks": (['hw 01', 'hw 02', 'hw 03'], 0.25),
...
...     # dictionary of assignment weights, followed by group weight.
...     "labs": ({"lab 01": .25, "lab 02": .75}, 0.25),
...
...     # a single number. the key is interpreted as an assignment name,
...     # and an assignment group consisting only of that assignment is
...     # created.
...     "exam": 0.5
... }
property late: DataFrame

A boolean dataframe telling which assignments were turned in late.

Will have the same index and columns as the points_earned attribute.

This is computed from the lateness attribute using the GradebookOptions.lateness_fudge option. If the lateness is less than the lateness fudge, the assignment is considered on-time; otherwise, it is considered late. This can be useful to work around grade sources whose reported lateness is not always reliable, such as Gradescope.

This is a derived attribute; it should not be modified.

property letter_grades: Series

A series containing the letter grade earned by each student.

A pandas Series with an entry for each student in the Gradebook. The index is the same as the series returned by the students attribute. Each entry is the letter grade the class, taking drops into account, and calculated using the value of the scale attribute.

This is a dynamically-computed property; it should not be modified.

Raises:

ValueError – If grading_groups has not yet been set.

property overall_score: Series

A series containing the overall score earned by each student.

A pandas Series with an entry for each student in the Gradebook. The index is the same as the series returned by the students attribute. Each entry is the overall score in the class, taking drops into account.

This is a derived attribute; it should not be modified.

Raises:

ValueError – If grading_groups has not yet been set.

property overall_weight: DataFrame

A table of assignment weights relative to all other assignments.

If grading_groups is set, this computes a table of the same size as points_earned containing for each student and assignment, the overall weight of that assignment relative to all other assignments.

If an assignment is not in an assignment group, the weight for that assignment is NaN. If no grading groups have been defined, all weights are Nan.

If the assignment is dropped for that student, the weight is zero. If all assignments in a group have been dropped, ValueError is raised.

Note that this is not the weight of the assignment relative to the total weight of the assignment group it is in. That is computed in weight.

This is a derived attribute; it should not be modified.

Raises:

ValueError – If all assignments in a group have been dropped for a student, the weights are undefined.

property pids: set[str]

All student PIDs.

This is a derived attribute; it should not be modified.

Return type:

set

remove_assignments(assignments: Collection[str])

Removes assignments from the gradebook.

Modifies the gradebook in-place.

If the grading_groups attribute been set, it is reset to an empty dictionary by this operation.

Parameters:

assignments (Collection[str]) – A collection of assignments names that will be removed.

rename_assignments(mapping: Mapping[str, str])

Renames assignments.

Modifies the gradebook in-place.

If the grading_groups attribute been set, it is reset to an empty dictionary by this operation.

Parameters:

mapping (dict[str, str]) – A mapping from existing column names to new names.

Raises:

ValueError – If a new name clashes with an existing name.

restrict_to_assignments(assignments: Collection[str])

Restrict the gradebook to only the supplied assignments, removing all others.

Modifies the gradebook in-place.

If the grading_groups attribute been set, it is reset to an empty dictionary by this operation.

Parameters:

assignments (Collection[str]) – A collection of assignment names.

restrict_to_students(to: Collection[str | Student])

Restrict the gradebook to only the supplied PIDs.

Parameters:

to (Collection[Union[str, Student]]) – A collection of PIDs or Students.

Raises:

KeyError – If a PID was specified that is not in the gradebook.

property score: DataFrame

A table of scores on each assignment.

Produces a DataFrame with a row for each student and a column for each assignment containing the number of points earned on that assignment as a proportion of the number of points possible on that assignment.

If the student did not attempt the assignment (and so the points_earned entry is NaN), the score is also NaN.

Does not take into account drops.

This is a derived attribute; it should not be modified.

property students: Students

All students as Student objects.

Returned in the order they appear in the indices of the points_earned attribute.

This is a derived attribute; it should not be modified.

Return type:

Students

property value: DataFrame

A table containing the value of each assignment for each student.

This produces a table of the same size as points_earned where each entry contains the value of an assignment for a given student. The “value” of an assignment is the amount that it contributes to the student’s overall score in the class. In short, it is the product of that assignment’s score with its overall weight.

If grading_groups is not set, all entries are NaN.

The total of a student’s assignment values equals their score in the class.

This is a derived attribute; it should not be modified.

Raises:

ValueError – If all assignments in a group have been dropped for a student, the weights are undefined.

property weight_in_group: DataFrame

A table of assignment weights relative to their assignment group.

If grading_groups is set, this computes a table of the same size as points_earned containing for each student and assignment, the weight of that assignment relative to the assignment group.

If an assignment is not in an assignment group, the weight for that assignment is NaN. If no grading groups have been defined, all weights are Nan.

If the assignment is dropped for that student, the weight is zero. If all assignments in a group have been dropped, ValueError is raised.

Note that this is not the overall weight towards to the overall score. That is computed in overall_weight.

This is a derived attribute; it should not be modified.

Raises:

ValueError – If all assignments in a group have been dropped for a student, the weights are undefined.

class gradelib.GradebookOptions(lateness_fudge: int = 300, allow_extra_credit: bool = True)

Configures the behavior of a Gradebook.

lateness_fudge

Number of seconds within which a late assignment is not considered late by Gradebook.late(). This can be useful to work around grade sources where the lateness may not be reliable, such as Gradescope. Default: 300.

Type:

int

allow_extra_credit

If True, grading group weights are allowed to sum to beyond one, effectively allowing extra credit. Default: True.

Type:

bool

class gradelib.GradingGroup(assignment_weights: Mapping[str, float], group_weight: float)

Represents a logical group of assignments and their weights.

assignment_weights

A dictionary mapping assignment names (strings) to their weight within the group (as a float between 0 and 1). Their weights should add to one.

Type:

Mapping[str, float]

group_weight

The overall weight of the group.

Type:

float

Raises:

ValueError – If the assignment weights are not between 0 and 1, they do not add to one, or if the group weight is not between 0 and 1.

property assignments: Assignments

The assignments in the group.