Initial import
This commit is contained in:
commit
62889999fe
89
process-gradescope-grades.py
Executable file
89
process-gradescope-grades.py
Executable file
|
@ -0,0 +1,89 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Script to ...
|
||||
#
|
||||
# Minimally tested. Seems to work. Use at your own risk.
|
||||
#
|
||||
# By James Eagan <james.eagan@telecom-paris.fr>
|
||||
# https://james.eagan.fr
|
||||
|
||||
import pandas as pd
|
||||
import re
|
||||
|
||||
skipCols = ['SID', 'Email', 'Submission ID', 'Submission Time',
|
||||
'Lateness (H:M:S)', 'View Count', 'Submission Count',
|
||||
]
|
||||
|
||||
def readCSV(fileName):
|
||||
cols = list(pd.read_csv(fileName, nrows=1))
|
||||
keepCols = [col for col in cols if col not in skipCols]
|
||||
|
||||
df = pd.read_csv(fileName, usecols=keepCols)
|
||||
df = df.sort_values(by='Nom')
|
||||
return df
|
||||
|
||||
pattern = re.compile(r'(\d+\.?\d*): (.+) \((\d+\.\d*) pts\)')
|
||||
def massageHeaders(df, args):
|
||||
multiHeaders = [[], [], []]
|
||||
|
||||
for header in df.columns:
|
||||
match = pattern.match(header)
|
||||
if match:
|
||||
# Question in the form: '11.4: types d'attributs (variables) (1.0 pts)'
|
||||
multiHeaders[0].append('Q' + match.group(1)) # Q1, Q2, Q3.1, Q3.2, etc
|
||||
multiHeaders[1].append(match.group(2)) # Question label
|
||||
multiHeaders[2].append(float(match.group(3))) # Question points (e.g. 1, 2, 1.5)
|
||||
else:
|
||||
multiHeaders[0].append('')
|
||||
multiHeaders[1].append('')
|
||||
multiHeaders[2].append(header)
|
||||
|
||||
df.columns = pd.MultiIndex.from_arrays(multiHeaders)
|
||||
return df
|
||||
|
||||
def writeExcel(df, fileName):
|
||||
with pd.ExcelWriter(fileName) as writer:
|
||||
df.to_excel(writer)
|
||||
# with open(basename + "-out.csv", 'w') as writer:
|
||||
# writer.write(df.to_csv())
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Massage Gradescope data")
|
||||
parser.add_argument("csv", help="csv file as exported from Gradescope")
|
||||
parser.add_argument("-o", "--out", help="file to write output")
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument("-,", "--commas", help="use commas for decimal separator", action="store_true")
|
||||
group.add_argument("-.", "--dots", help="use dots for decimal separator", action="store_true")
|
||||
group.add_argument("-d", "--decimal-separator", help="decimal separator for real numbers", default=",")
|
||||
parser.add_argument("-s", "--sep", help="csv column separator (default: ',' when decimal separator is '.' and ';' for ',')")
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.commas:
|
||||
args.decimal_separator = ","
|
||||
elif args.dots:
|
||||
args.decimal_separator = "."
|
||||
|
||||
if not args.sep:
|
||||
args.sep = ';' if args.decimal_separator == ',' else ','
|
||||
|
||||
return args
|
||||
|
||||
def writeOutput(df, args):
|
||||
if args.out:
|
||||
writeExcel(df, args.out)
|
||||
else :
|
||||
df.to_csv(sys.stdout, sep=args.sep, decimal=args.decimal_separator)
|
||||
|
||||
def nowDoIt():
|
||||
args = parse_args()
|
||||
df = readCSV(args.csv)
|
||||
massageHeaders(df, args)
|
||||
writeOutput(df, args)
|
||||
|
||||
nowDoIt()
|
||||
|
Loading…
Reference in a new issue