Ed Helper#
This notebook is meant to assist with Between-Class Participation grading. To use:
Download the Discussion data
Open analytics
Download the Threads JSON
Adjust the filename and dates below
Run all cells in the notebook
Review the student contributions at the bottom
import pandas as pd
FILENAME = "FILEPATH.json"
# dates are inclusive; 1-based
START = pd.Timestamp(year=2026, month=1, day=28, tz="US/Eastern")
# add a day, since the default time is 00:00:00
END = pd.Timestamp(year=2026, month=2, day=3, tz="US/Eastern") + pd.Timedelta(days=1)
Load data#
import json
import pandas as pd
data = json.load(open(FILENAME))
Include replies#
The JSON data includes reples (comments and answers) as nested under each post.
from typing import Any
def flatten_nested_items(items: list[dict[str, Any]]):
"""Recursively flatten all nested comments/answers."""
flattened = items.copy()
for item in items:
for field in ["comments", "answers"]:
if field in item:
nested_items = item[field]
flattened_nested_items = flatten_nested_items(nested_items)
flattened.extend(flattened_nested_items)
return flattened
flattened_data = flatten_nested_items(data)
# flattened_data
Convert to DataFrame#
posts = pd.json_normalize(flattened_data)
posts.info()
posts["created_at"] = pd.to_datetime(posts["created_at"])
# posts["created_at"]
Filter#
output = posts[(posts["created_at"] >= START) & (posts["created_at"] < END)]
print(output["created_at"].min())
print(output["created_at"].max())
Prep output#
# exclude the instructors
output = output[output["user.role"] != "admin"]
# sort by name
output = output.sort_values(["user.name", "created_at"])
# only include a subset of the columns
output = output[
[
"user.name",
# "user.email",
"url",
# "created_at",
# "title",
"text",
]
]
# make links clickable
# https://stackoverflow.com/a/20043785/358804
output["url"] = output["url"].apply(lambda url: f'<a href="{url}">Open</a>')
# render newlines
# https://stackoverflow.com/a/56881411/358804
styled = output.style.set_properties(
**{
"text-align": "left",
"white-space": "pre-wrap",
}
)
Output#
from IPython.display import HTML
HTML(styled.to_html(escape=False))