Grading Policies

Common grading policies are implemented in gradelib as functions that modify the core data attributes of a Gradebook. You can find these in the gradelib.policies module.

Handling late assignments

The gradelib.policies.lates.penalize() function penalizes late assignments. Its implementation is very flexible, and allows you to specify creative late policies.

For example, suppose we have the following grades:

>>> gradebook.points_earned
          Homework 01  Homework 02  Homework 03
<Justin>          7.0          5.0          9.0
<Barack>         10.0          8.0          7.0

Some of the assignments have been turned in late:

>>> gradebook.late
        Homework 01  Homework 02  Homework 03
Justin         True         True         True
Barack         True        False        False

By default, the gradelib.policies.lates.penalize() function will penalize late assignments by giving them zero points (a 100% deduction):

>>> gradelib.policies.lates.penalize(gradebook)
>>> gradebook.points_earned
          Homework 01  Homework 02  Homework 03
<Justin>          0.0          0.0          0.0
<Barack>          0.0          8.0          7.0

If we want to deduct a different percentage, we can specify that as an argument:

>>> from gradelib import Percentage
>>> from gradelib.policies.lates import Deduct
>>> gradelib.policies.lates.penalize(gradebook, policy=Deduct(Percentage(50)))
>>> gradebook.points_earned
          Homework 01  Homework 02  Homework 03
<Justin>          3.5          2.5          4.5
<Barack>          5.0          8.0          7.0

A common policy is to forgive a certain number of late assignments. For example, we might want to forgive the first two late assignments, but penalize all subsequent lates. We can do this with gradelib.policies.lates.Forgive:

>>> from gradelib.policies.lates import Forgive
>>> gradelib.policies.lates.penalize(gradebook, policy=Forgive(2))
>>> gradebook.points_earned
          Homework 01  Homework 02  Homework 03
<Justin>          7.0          5.0          0.0
<Barack>         10.0          8.0          7.0

Notice how Justin’s third assignment was penalized, but his first two were not.

The policy argument to gradelib.policies.lates.penalize() can be used to specify very creative late policies. It accepts a callable that takes a gradelib.policies.lates.LateInfo object describing a late assignment and returns a gradelib.Points or gradelib.Percentage object specifying the deduction for that late.

For example, suppose we want to penalize late assignments by 10% for each hour they are late, up to a maximum of 50%. We can do this with the following function:

>>> from gradelib import Percentage
>>> def penalize_10_per_hour(late_info):
...     seconds_late = late_info.gradebook.lateness.loc[
...         late_info.student, late_info.assignment
...     ].seconds
...     hours_late = seconds_late / 3600
...     return Percentage(min(50, 10 * hours_late))
>>> gradelib.policies.lates.penalize(gradebook, policy=penalize_10_per_hour)

Dropping low scores

Another common grading policy is to drop the lowest score in a category. This can be done in gradelib with the gradelib.policies.drops.drop_most_favorable() function. Note that dropping the lowest score in a category is not necessarily the most favorable to the student, and this function instead finds the assignment that will increase their overall score the most.

Giving multiple chances at an assignment

The gradelib.policies.attempts.take_best() function allows you to give students multiple chances at an assignment. By default, it takes the maximum score of all attempts, but you can specify a policy that penalizes multiple attempts.

For example, to penalize each attempt by 10%, you can do the following:

>>> from gradelib.policies.attempts import take_best
>>> gradebook.score
           Exam - Attempt 01  Exam - Attempt 02  Exam - Attempt 03
<Alice>                  0.9                NaN                NaN
<Barack>                 0.5               0.70                1.0
<Charlie>                0.7               0.85                NaN
>>> def penalize_10_per_attempt(i, raw_score):
...     return raw_score * (1 - 0.1 * i)
>>> take_best(
...     gradebook,
...     attempts=gradebook.assignments.group_by(lambda s: s.split(" - ")[0].strip()),
...     policy=penalize_10_per_attempt
... )
>>> gradebook.score
            Exam
<Alice>    0.900
<Barack>   0.800
<Charlie>  0.765

Tracking exceptions

The gradelib.policies.exceptions.make_exceptions() function allows you to make grading exceptions for individual students. It adds notes to the gradebook that appear in the student’s grade summary, making the exception clear to the student.