How to join assignment logs with outcomes in Python
Merge submission log entries with grading outcomes using left join and full outer join patterns in pure Python.
Python code
53 linesfrom datetime import datetime, timedelta
class AssignmentLog:
def __init__(self):
self.logs = [
{"assignment_id": 101, "student_id": "S001", "submitted_at": "2024-03-01 10:30:00"},
{"assignment_id": 101, "student_id": "S002", "submitted_at": "2024-03-02 14:15:00"},
{"assignment_id": 102, "student_id": "S001", "submitted_at": "2024-03-05 09:45:00"},
]
self.outcomes = [
{"assignment_id": 101, "student_id": "S001", "grade": "A"},
{"assignment_id": 101, "student_id": "S002", "grade": "B"},
{"assignment_id": 102, "student_id": "S003", "grade": "C"},
]
def join_outcomes_present(self):
"""Left join: all log entries, outcome grade if exists."""
result = []
for log in self.logs:
matched = [o for o in self.outcomes
if o["assignment_id"] == log["assignment_id"]
and o["student_id"] == log["student_id"]]
row = dict(log)
row["grade"] = matched[0]["grade"] if matched else None
result.append(row)
return result
def join_outcomes_all(self):
"""Full outer join mock: union of log keys and outcome keys."""
keys = set((l["assignment_id"], l["student_id"]) for l in self.logs)
keys |= set((o["assignment_id"], o["student_id"]) for o in self.outcomes)
result = []
for aid, sid in sorted(keys):
log_match = next((l for l in self.logs
if l["assignment_id"] == aid and l["student_id"] == sid), None)
out_match = next((o for o in self.outcomes
if o["assignment_id"] == aid and o["student_id"] == sid), None)
result.append({
"assignment_id": aid,
"student_id": sid,
"submitted_at": log_match["submitted_at"] if log_match else None,
"grade": out_match["grade"] if out_match else None,
})
return result
if __name__ == "__main__":
log = AssignmentLog()
print("Left Join (log-driven):")
for row in log.join_outcomes_present():
print(row)
print("\nFull Outer Join:")
for row in log.join_outcomes_all():
print(row)
Output
Left Join (log-driven):
{'assignment_id': 101, 'student_id': 'S001', 'submitted_at': '2024-03-01 10:30:00', 'grade': 'A'}
{'assignment_id': 101, 'student_id': 'S002', 'submitted_at': '2024-03-02 14:15:00', 'grade': 'B'}
{'assignment_id': 102, 'student_id': 'S001', 'submitted_at': '2024-03-05 09:45:00', 'grade': None}
Full Outer Join:
{'assignment_id': 101, 'student_id': 'S001', 'submitted_at': '2024-03-01 10:30:00', 'grade': 'A'}
{'assignment_id': 101, 'student_id': 'S002', 'submitted_at': '2024-03-02 14:15:00', 'grade': 'B'}
{'assignment_id': 102, 'student_id': 'S001', 'submitted_at': '2024-03-05 09:45:00', 'grade': None}
{'assignment_id': 102, 'student_id': 'S003', 'submitted_at': None, 'grade': 'C'}
How it works
This code simulates SQL-style joins with Python lists and dicts. The left join keeps every log entry and attaches a grade only when a matching outcome exists, using a list comprehension to find matches. The full outer join builds a union of all unique (assignment_id, student_id) pairs, then looks up each side independently. Both methods use dictionary key equality as the join condition, which mirrors how you'd combine experiment data tables. The dict(log) copy ensures the original logs stay unmodified when adding the grade field.
Common mistakes
- Forgetting to match on both assignment_id and student_id, causing cross-joins.
- Mutating the original log dictionaries instead of copying them with dict(log).
- Assuming every log has an outcome, so accessing matched[0] without checking raises IndexError.
Variations
- Use pandas merge with how='left' or how='outer' on DataFrames for larger datasets.
- Use SQLite in-memory tables with two SELECT queries for declarative joins.
Real-world use cases
- Merging event telemetry from an experiment with user bucketing data to compute per-variant metrics.
- Reconciling survey responses against participant enrollment lists to identify missing respondent data.
- Combining task logs with completion grades in an A/B testing platform to evaluate feature impact.
Sponsored
More from A/B testing & experimentation
Keep learning
Related tutorials and quizzes for this topic.