aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamil Staps2016-07-22 16:02:06 +0200
committerCamil Staps2016-07-22 16:02:06 +0200
commit65683154ff1a20d76259606f691f02c3719c7b42 (patch)
tree1a8798c1db1d0c4b3683f4e2ef87ffb193b541f2
parentInitial readme; plotgrades.py (diff)
--where-has added
-rwxr-xr-xplotgrades.py42
1 files changed, 35 insertions, 7 deletions
diff --git a/plotgrades.py b/plotgrades.py
index 9973627..165d0bc 100755
--- a/plotgrades.py
+++ b/plotgrades.py
@@ -64,14 +64,23 @@ def remove_empty_lists(headers, data):
new_data.append(d)
return new_headers, new_data
-def regex_callback(header, regex='', invert=False):
+def header_regex_callback(header, regex='', invert=False):
"""Check whether a regex occurs in a header
This is an example of a possible callback function."""
match = re.compile(regex).search(header) != None
return match != invert
-def check_callback(headers, data, header_callback):
+def participant_wherehas_callback(headers, participant, regex='', invert=False):
+ """Check whether a participant has a grade for some assignment"""
+ regex = re.compile(regex)
+ mh = [regex.search(h) != None for h in headers[6:]]
+ for h, d in zip(mh, participant[6:]):
+ if h and d != '':
+ return (not invert)
+ return invert
+
+def check_header_callback(headers, data, header_callback):
"""For each header, check that we want to show it, and remove data if not"""
new_headers, new_data = [], []
for h, d in zip(headers, data):
@@ -80,12 +89,23 @@ def check_callback(headers, data, header_callback):
new_data.append(d)
return new_headers, new_data
-def plotgrades(headers, data, header_callback=lambda x:True):
+def check_participant_callback(headers, data, participant_callback):
+ """For each participant, check that we want to show it, and remove if not"""
+ new_data = []
+ for d in data:
+ if participant_callback(headers, d):
+ new_data.append(d)
+ return new_data
+
+def plotgrades(headers, data, skip=0,
+ participant_callback=lambda x:True, header_callback=lambda x:True):
"""Plot grades corresponding to headers in a boxplot"""
+ data = check_participant_callback(headers, data, participant_callback)
+ headers, data = headers[skip:], data[skip:]
data = parse_floats(data)
data = remove_zeros(data)
headers, data = remove_empty_lists(headers, data)
- headers, data = check_callback(headers, data, header_callback)
+ headers, data = check_header_callback(headers, data, header_callback)
data = normalise(data)
headers = [strip_header(h) for h in headers]
@@ -106,8 +126,12 @@ def parse_args():
help='Skip the first n columns')
pars.add_argument('-w', '--where', metavar='regex', default='',
help='Restrict what grades are shown with a regex')
- pars.add_argument('-i', '--invert', action='store_true',
+ pars.add_argument('-wh', '--where-has', metavar='regex', default='',
+ help='Only count participants with a grade for a matching item')
+ pars.add_argument('-iw', '--invert-where', action='store_true',
help='Invert --where regex')
+ pars.add_argument('-iwh', '--invert-where-has', action='store_true',
+ help='Invert --where-has regex')
pars.add_argument('filename', metavar='file',
help='The CSV file as exported by BlackBoard')
@@ -117,8 +141,12 @@ def main():
"""Plot BlackBoard grades from a CSV file in boxplots"""
args = parse_args()
headers, data = readcsv(args.filename)
- plotgrades(headers[args.skip:], data[:,args.skip:],
- partial(regex_callback, regex=args.where, invert=args.invert))
+
+ plotgrades(headers, data, skip=args.skip,
+ header_callback=partial(header_regex_callback,
+ regex=args.where, invert=args.invert_where),
+ participant_callback=partial(participant_wherehas_callback,
+ regex=args.where_has, invert=args.invert_where_has))
if __name__ == '__main__':
main()