Take Average of Quiz data using python ( Troubleshooting) - python

I need to read in the scores from a file of students quizzes, and return the highest score out of the 3 attempts.I need to use hash/dictionary in python. Here is what I have so far.
STD_ID = {}
ATTEMPTS = {}
SCORE= {}
f= open("std_attempt_score.txt", "r")
line = f.readline()
for line in f:
line = line.rstrip()
ents = line.split("\t")
did = ents[1]
if did in STD_ID:
ATTEMPTS[did] += 3
SCORE[did] += int(ents[2])
else:
STD_ID[did] = ents[2]
ATTEMPTS[did] = 3
SCORE[did] = int(ents[2])
for key in STD_ID:
print("Avg score for Student", key, "=",SCORE)
Text data in file.
FILE
STD_ID ATT_NUM SCORE
S23Y 1 85
S03X 1 80
S34Z 1 19
S54M 1 23
S34Z 2 25
S01X 1 79
S03X 2 10
S23Y 2 09
S34Z 3 92
S54M 2 96
S23Y 3 74
S54M 3 65
S03X 3 54
My results are as follows:
Avg score for Student 1 = {'1': 286, '2': 140, '3': 285}
Avg score for Student 2 = {'1': 286, '2': 140, '3': 285}
Avg score for Student 3 = {'1': 286, '2': 140, '3': 285}

If you don't need to store the score for each attempt then why not just replace the value if it's higher than the currently recorded attempt?
students = {}
f = open("std_attempt_score.txt", "r")
line = f.readline()
for line in f:
line = line.rstrip()
ents = line.split(",")
student_id = ents[0]
attempt_score = int(ents[2])
score = students.setdefault(student_id, attempt_score)
if attempt_score > score:
students[student_id] = attempt_score
for student_id, score in students.items():
print("Highest score for Student", student_id, "=", score)

Issues with the given code :
Loop starts with a text header which is not checked before going to if else statements for student_id checks .Printing the same value of SCORE at the end of code.no average is taken in script.
Fixed code
Here is a sample code
STD_ID = {}
ATTEMPTS = {}
SCORE= {}
f= open("std_attempt_score.txt", "r")
line = f.readline()
for line in f:
line = line.rstrip()
entss = " ".join(line.split())
ents = entss.split(" ")
did = ents[0]
if not line.startswith("STD_ID"): # check for the header you definitely want to skip this line
if did in STD_ID :
ATTEMPTS[did] += 1
SCORE[did].append(int(ents[2])) #polulate student_id with marks
else:
STD_ID[did] = [ents[0]] #Start Dictionary with student ID and marks
ATTEMPTS[did] = 1
SCORE[did] = [int(ents[2])]
for key in sorted(STD_ID):
if len(SCORE[key]) < 3:
dumValues = [0] * (3 - len(SCORE[key]))
SCORE[key] = SCORE[key] + dumValues # add 0's in un-attempted quizzes.
print("Student ID {0} Score Summary : \n".format(key))
print("Top 3 Quiz : ", sorted(SCORE[key], reverse=True)[:3])
print("Avg score of top 3 quiz : " , sum(sorted(SCORE[key], reverse=True)[:3]) / 3)
print("Quiz With Highest Marks out of 3 Top Quizzes : ", sorted(SCORE[key], reverse=True)[0])
print("Total Marks in 3 Attempts : ", sum(sorted(SCORE[key], reverse=True)[:3]), "\n\n")
Sample Output:
Student ID S01X Score Summary :
Top 3 Quiz : [79, 0, 0]
Avg score of top 3 quiz : 26.333333333333332
Quiz With Highest Marks out of 3 Top Quizzes : 79
Total Marks in 3 Attempts : 79
Student ID S03X Score Summary :
Top 3 Quiz : [80, 54, 10]
Avg score of top 3 quiz : 48.0
Quiz With Highest Marks out of 3 Top Quizzes : 80
Total Marks in 3 Attempts : 144
Student ID S23Y Score Summary :
Top 3 Quiz : [85, 74, 9]
Avg score of top 3 quiz : 56.0
Quiz With Highest Marks out of 3 Top Quizzes : 85
Total Marks in 3 Attempts : 168
Student ID S34Z Score Summary :
Top 3 Quiz : [92, 25, 19]
Avg score of top 3 quiz : 45.333333333333336
Quiz With Highest Marks out of 3 Top Quizzes : 92
Total Marks in 3 Attempts : 136
Student ID S54M Score Summary :
Top 3 Quiz : [96, 65, 23]
Avg score of top 3 quiz : 61.333333333333336
Quiz With Highest Marks out of 3 Top Quizzes : 96
Total Marks in 3 Attempts : 184

Related

Trying to find max value from a list of values generated from a loop

I am really new to python and have been working on this with the help of others.
I am trying to figure out the right way to go about finding the max of the list acct_all_total.
Everything else works if I remove the part w/ the max function.
erros i get: TypeError: 'int' object is not iterable.
Or I get 0 as a result.
def inventory(info, months_subscribed, add_free_months, video_on_demand):
acct_all_total = 0
acct_max = 0
# here you init the total value to 0
if info.get('months_subscribed') == 3:
months_subscribed_total = info.get('months_subscribed') * 18
elif info.get('months_subscribed') < 3:
months_subscribed_total = info['months_subscribed'] * 7
elif info.get('months_subscribed') > 3:
months_subscribed_total = info['months_subscribed'] - 3 * 7 + 18
print(f"User {info.get('name')} has months subscribed total of : $ {months_subscribed_total} ")
if info['ad_free_months'] > 0:
ad_free_total = info.get('ad_free_months') * 2
print(f" User {info.get('name')} total ad free is : $ {ad_free_total} ")
if info['video_on_demand'] > 0:
video_on_demand_total = info.get('video_on_demand') * 27.99
print(f" User {info.get('name')} total video on demand is $ : {video_on_demand_total} ")
acct_all_total = int(months_subscribed_total + ad_free_total + video_on_demand_total)
# acct_all_total = [int(acct_all_total)]
print(f"Total for {info.get('name')} is: {acct_all_total} ")
# acct_max = (max(acct_all_total)) #if I use these hashtag parts I get the type error mentioned above.
# if int(acct_all_total) > int(acct_all_total):
# acct_max = int(acct_all_total)
# print(f" User {info.get('name')} max value is: {acct_max} ")
return acct_all_total ; acct_max
acct_info = [{'name': 'acct_1', 'months_subscribed': 2, 'ad_free_months': 3, 'video_on_demand': 1},
{'name': 'acct_2', 'months_subscribed': 1, 'ad_free_months': 2, 'video_on_demand': 2},
{'name': 'acct_3', 'months_subscribed': 2, 'ad_free_months': 1, 'video_on_demand': 3}]
acct_max = 0
combined_total = 0
months_subscribed = 0
ad_free_months = 0
video_on_demand = 0
months_subscribed_total = 0
ad_free_total = 0
video_on_demand_total = 0
acct_all_total = 0
for acct in acct_info:
print("--")
acct_all_total+=inventory(acct, months_subscribed, ad_free_months, video_on_demand)
for acct in acct_info: #when I try it this way I get 0 as a result
if int(acct_all_total) > int(acct_all_total):
acct_max = acct_all_total
print("Total for all accounts:",acct_all_total)
Example of Output:
User acct_1 has months subscribed total of : $ 14
User acct_1 total ad free is : $ 6
User acct_1 total video on demand is $ : 27.99
Total for acct_1 is: 47
--
User acct_2 has months subscribed total of : $ 7
User acct_2 total ad free is : $ 4
User acct_2 total video on demand is $ : 55.98
Total for acct_2 is: 66
--
User acct_3 has months subscribed total of : $ 14
User acct_3 total ad free is : $ 2
User acct_3 total video on demand is $ : 83.97
Total for acct_3 is: 99
Total for all accounts: 212
0
To get the biggest number in a list you can sort it first and then get the first or last item in the list.
obj = [1, 6, 9, 123, 64, 12]
obj.sort() # Sorts the list into this: [1, 6, 9, 12, 64, 123]
print(obj[-1]) # [-1] Returns the last item in the list
Make sure the list does not contain strings as the sort function will not sort strings mixed with integers or floats.
Note that your "acct_all_total" is not a list, a list is defined with [] (insert a reference to docs or other basic explanation).
Edit:
I would like to clarify that you're probably better off researching a bit more about the different types of objects there are in python, how to use them and when to use which one.

Program to enter 5 student mark across 4 subjects and output highest average mark of student and subject

I am trying to write a program where i need to be able to enter 5 student marks across 4 different subjects and then output the highest average mark of both the student and the subject.
The desired input and output is :
Student 1 (courses 1-4): 50 60 70 60
Student 2 (courses 1-4): 100 90 87 90
Student 3 (courses 1-4): 70 100 90 90
Student 4 (courses 1-4): 30 65 50 50
Student 5 (courses 1-4): 58 50 74 43
The highest average mark of students: 91.75
The highest average mark of courses: 74.2
The current code I have works for calculating for one subject and not 4. How am I able to enter 4 grades per student to get my desired output.
see my code below:
m1 = int(input("Student 1 (courses 1-4): "))
m2 = int(input("Student 2 (courses 1-4): "))
m3 = int(input("Student 3 (courses 1-4): "))
m4 = int(input("Student 4 (courses 1-4): "))
m5 = int(input("Student 5 (courses 1-4): "))
avg = (m1 + m2+ m3+ m4 + m5) / 5;
avg1 =(m1 + m2+ m3+ m4 + m5) / 20;
print("The Highest average mark of students =", avg)
print("The Highest average mark of courses =", avg1)
This code does the job,
import pandas as pd
import numpy as np
# Part 1
student_num = 5
all_marks = []
for i in range(student_num):
marks = input(f"Student {i + 1} (courses 1-4): ")
all_marks.append(list(map(float, marks.split(" "))))
# Part 2
df = pd.DataFrame(all_marks, columns = ['Marks'])
course_avg = df.Marks.apply(np.mean)
student_avg = df.Marks.apply(np.mean, axis = 1)
The first part of the code converts the input into numbers and stores them into a list. This list is then converted into a data frame in Part 2. I firstly apply np.mean on the columns to find the average for each course, then on the rows to find the average for each student.
You can use idxmax() on both course_avg and student_avg to find the index of the maximum average and find the course/student with the highest average accordingly.
(It's better to store the values in a .xlsx or .csv file directly instead of inputing them through Python this way. Once you have the files, just pass the file path in pd.read_excel() or pd.read_csv() depending upon the format of the file.)
First, create a dictionary to take the inputs of marks for each student. Lets call it d_marks. Create a dictionary to get the average of all students. Let's call it avg_marks. Create a dictionary to get the total marks of all courses. Let's call it avg_course. After that get the max of them. Here's how you can do it:
d_marks = {}
avg_marks = {}
avg_course = {}
for i in range(1,6): # We loop for 5 students
d_marks[f'Student {i} (courses 1-4)'] = list(map(int, input(f"Student {i} (courses 1-4): ").split())) # Split the string and creates an integer list
avg_marks[f'Average of Student {i}'] = sum(d_marks[f'Student {i} (courses 1-4)']) / len(d_marks[f'Student {i} (courses 1-4)']) #Create average dictionary for Students
for j in range(1, len(d_marks[f'Student {i} (courses 1-4)'])+1):
if f'Course {j} sum' in avg_course: # if course sum already in dictionary then add it to previous.
avg_course[f'Course {j} sum'] += d_marks[f'Student {i} (courses 1-4)'][j-1]
else:
avg_course[f'Course {j} sum'] = d_marks[f'Student {i} (courses 1-4)'][j-1] # if course sum not in dictionary then create one.
print("The Highest average mark of students =", max(avg_marks.values()))
print("The Highest average mark of courses =", max(avg_course.values())/ len(d_marks))
Output:
Student 1 (courses 1-4): 50 60 70 60
Student 2 (courses 1-4): 100 90 87 90
Student 3 (courses 1-4): 70 100 90 90
Student 4 (courses 1-4): 30 65 50 50
Student 5 (courses 1-4): 58 50 74 43
The Highest average mark of students = 91.75
The Highest average mark of courses = 74.2

Iterate over dataframe for a value in multiple columns and print something for each row returned

Using the example dataframe below,
How do I iterate over both Grade 1 and Grade 2 columns to select any grade 1 greater than 24 with any Grade 2 greater than 50 using list_comprehension or vectorization mentioned here
import pandas as pd
data = {'Name':['Jai', 'Princi', 'Gaurav', 'Anuj'],
'Grade 1':[27, 24, 22, 32],
'Grade 2':[60, 50, 75, 60],
'Final Grade':[77, 74, 97, 92]}
df = pd.DataFrame(data)
print(df[['Name', 'Grade 1', 'Grade 2','Final Grade']])
Based on those conditions I would like the expected output to return something like:
Jai has Grade 1 score of 27 and Grade 2 score of 60
Anuj has Grade 1 score of 32 and Grade 2 score 60
Gaurav has Grade 1 score of 22 and Grade 2 score of 75
Following a tutorial but trying to go beyond in understanding how to implement either of those concepts.
Your question isn't really clear so I hope you can clarify things a bit. For example, you need Grade 1 which are greater than 24 but in your expected output, you are expecting Gaurav with 22.
However, to make things simpler, I would say never try to iterate in pandas. At the very least, it is a practice that is best left for exception cases.
Here you can use conditional assignments :
df[(df['Grade 1'] > 24) & (df['Grade 2'] > 50 )]]
out :
Name Grade 1 Grade 2 Final Grade
Jai 27 60 77
Anuj 32 60 92
Edit : If in case you wish to have an output with either Grade 1 > 24 OR Grade 2 > 50, just replace & with '|'
Do you mean something like this?
res = df[(df['Grade 1'] > 24) & (df['Grade 2'] > 50)]
print(res)
Name Grade 1 Grade 2 Final Grade
0 Jai 27 60 77
3 Anuj 32 60 92
You can use apply, although, in this case, I do not think it will make too much difference.
df[(df["Grade 1"] > 24) & (df["Grade 2"] > 50)].apply(
lambda x: f"{x['Name']} has Grade 1 score of {x['Grade 1']} and Grade 2 score of {x['Grade 2']}",
axis=1,
).tolist()
['Jai has Grade 1 score of 27 and Grade 2 score of 60',
'Anuj has Grade 1 score of 32 and Grade 2 score of 60']

How to sum specific integer values of Python List

I'm trying to sum integer values from the list using sum function. Unfortunately, it is adding all the values of the list but not those which I need from the user.
Here is my code:
tourist_attractions = []
distance = []
entry_cost = []
for i in range(3):
tourist_attractions.append (input("Enter Tourist place: "))
tourist_distance =(int(input("Enter distance: ")))
if tourist_distance > 50:
print("Invalid Entry")
continue
if tourist_distance <= 50:
distance.append(tourist_distance)
cost = (float(input("Enter cost: ")))
if cost > 100:
print("cost must be between 1-100")
continue
if cost > 0 or cost <= 100:
entry_cost.append(cost)
print()
for line in tourist_attractions:
print("Place:", line)
for line in distance:
print("Distance:", line)
for line in entry_cost:
print("Cost:", line)
print()
number_of_places_to_visit = int(input("Total number of places to visit: "))
x = 1
while x <= number_of_places_to_visit:
select_tourist_place = input("select tourist place, 0-3: ")
x = x + 1
if select_tourist_place == "0":
print(tourist_attractions[0], distance[0], entry_cost[0])
elif select_tourist_place == "1":
print(tourist_attractions[1], distance[1], entry_cost[1])
elif select_tourist_place == "2":
print(tourist_attractions[2], distance[2], entry_cost[2])
elif select_tourist_place == "3":
print(tourist_attractions[3], distance[3], entry_cost[3])
elif select_tourist_place == "4":
print(tourist_attractions[4], distance[4], entry_cost[4])
print("total cost: " , sum(entry_cost))
Result I am getting:
Enter Tourist place: London
Enter distance: 25
Enter cost: 15
Enter Tourist place: Manchester
Enter distance: 30
Enter cost: 15
Enter Tourist place: Scotland
Enter distance: 50
Enter cost: 20
Place: London
Place: Manchester
Place: Scotland
Distance: 25
Distance: 30
Distance: 50
Cost: 15.0
Cost: 15.0
Cost: 20.0
Total number of places to visit: 2
select tourist place, 0-3: 0
London 25 15.0
select tourist place, 0-5: 1
Manchester 30 15.0
total cost: 50.0
>>>
I can understand, at the moment it is summing up all the appended list of entry_cost and giving me the total of 50 which should be 15 from London and 15 from Manchester. Any help?
print("total cost: " , sum(entry_cost))
definitely states your are iterating over ALL entry costs. You would want to store the selected indices and sum over the entries of those indices.

Strings and Integers in Python

This is my data file (called “studentdata.txt”)
joe 10 15 20 30 40
bill 23 16 19 22
sue 8 22 17 14 32 17 24 21 2 9 11 17
grace 12 28 21 45 26 10
john 14 32 25 16 89
I need to calculate the average grade for each student and print out the student’s name along with their average grade. I can extract the name with no problem and determine the number of exam scores, but I can not figure out how to sum the exam scores. This is what I have so far:
file=open("studentdata.txt","r")
for aline in file:
data=aline.split()
print((data[0]),"Average grade:")
print(len(data[1:]))
file.close()
It seems like you have most of this already done, and you already have a good grasp of how to partition each line into the two components you need, so you're real close!
First, since the data is being read in as a string, you need to convert part of your data to integers:
for line in file:
tmp = line.split()
name, scores = tmp[0], list(map(int, tmp[1:]))
This will give us each name, along with a list of scores as integers. Now all you have to do is find the average:
average = sum(scores)/len(scores)
Let's tie it all together by assigning to a dictionary:
dct[name] = average
And we get:
{'joe': 23.0, 'bill': 20.0, 'sue': 16.166666666666668, 'grace': 23.666666666666668, 'john': 35.2}
Try this?
file = open("studentdata.txt", "r")
for aline in file:
data = aline.split()
# Convert list of string numerals to int
grades = [int(grade) for grade in data[1:]]
# Find average by dividing sum by length of numbers list
average = sum(grades)/len(data[1:])
print((data[0]), "Average grade:", str(average))
file.close()
Try the below code, just split each line on spaces then get the numbers not with the name so the indexing will be the i.strip().split()[1:] then use map to convert that into an integer then use statistics.mean to get the average:
from statistics import mean
d = {}
with open('studentdata.txt','r') as f:
for i in f.readlines():
d[i.split()[0]] = mean(list(map(int,i.strip().split()[1:])))
print(d)
Output:
{'joe': 23.0, 'bill': 20.0, 'sue': 16.166666666666668, 'grace': 23.666666666666668, 'john': 35.2}

Categories