0

I have created a text file that will hold a student's name as well as their grade in the format:

name1, 1
name2, 3
name3, 2
name1, 7
...

I have printed to the text file in the format:

file=open(studentclass+' Grades.txt', 'a')
file.write(name + ', ' + score + '\n')
file.close()

How would I calculate an average score for each name with Python using the score instead of the names?

A Bo
  • 45
  • 2
  • 5
  • 2
    Can you show what you've tried, all you're doing is opening the file and writing the name value and score without any attempt to sum the scores and calculate the mean – EdChum Mar 07 '16 at 14:14
  • My file lists the name and score of each user with a comma in between, my code is formatted so that someone with the same name will have multiple lines with their name and then a score. I want to find the average of all the people with the same name. – A Bo Mar 07 '16 at 14:26
  • @ABo You really should specify that in the question. As is, L3viathan's perfectly good answer doesn't address your question because your original post was undercontsrained – en_Knight Mar 07 '16 at 14:33

1 Answers1

1

This should work:

from collections import defaultdict
from itertools import chain

grades = defaultdict(list)
with open("Grades.txt") as f:
    for line in f:
        name, score = line.split(", ")
        grades[name].append(int(score))

for name in grades:
    print(name, sum(grades[name])/len(grades[name]), sep=": ")

print("Total average (student average):",
      sum(sum(grades[name])/len(grades[name]) for name in grades) / len(grades))
print("Total average (raw):",
      sum(chain.from_iterable(grades[name] for name in grades)) / sum(len(grades[name]) for name in grades))

edit: Changed to meet requirements of per-student averages.

edit: Added global averages.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • Do you mean to have integer division in the mean function? This will result in integer division in python 2 (question marked python 3), but why not just cast to floats so its unambiguous (and if someone scores 92.5 it won't be truncated)? Also why are we writing a custom mean function, aren't there a lot of those in python (e.g., numpy)? – en_Knight Mar 07 '16 at 14:21
  • @en_Knight a) If it's a Python 3 question, I'll give a Python 3 answer. b) I'm not a big fan of adding huge dependencies like numpy for something so simple where speed really won't be an issue. In this case, I would even doubt numpy would be any faster. – L3viathan Mar 07 '16 at 14:24
  • I guess that's fair... but what about any of these http://stackoverflow.com/questions/9039961/finding-the-average-of-a-list 100+ voted methods that are one line without any dependencies? The accepted answer on that question even makes it easy to provide the cast from str with a few more characters – en_Knight Mar 07 '16 at 14:31
  • Also this doesn't address the problem of retrieving per-name averagse, as specified in the comments. I don't fault you for that, it was added after the question was posted, but as is this is missing that important info – en_Knight Mar 07 '16 at 14:32
  • @en_Knight Will change it to have per-name averages, but the reason I didn't do `sum/len` is that it will not work on a file object (unless you load it into memory completey). – L3viathan Mar 07 '16 at 14:44
  • Okay +1 I've given you a hard enough time on a perfectly good answer I think :) – en_Knight Mar 07 '16 at 14:50
  • How would I go about calculating the total score? – A Bo Mar 08 '16 at 13:09
  • @ABo You mean like overall averages? See the last two lines. – L3viathan Mar 09 '16 at 01:47
  • @L3viathan Sorry to bother you again after all this code, I was testing your code and found that the global average(raw) works perfectly, however I was wondering what the variable 'totals' is supposed to represent in the line: for name in totals: - this code produced an error as I have not stated what totals is supposed to be. – A Bo Mar 14 '16 at 14:15
  • @ABo Oh, sorry, that got lost in the edit history. I meant `grades`, of course. – L3viathan Mar 14 '16 at 22:46