0

The premise of my project is that I've been tasked with having creating a Python code that takes in user input (specifically letter grades) and places them into an array, converts them into the appropriate number grade/gpa, then calculates the z score for said grades. This is what I have so far and everything compiles fine up until the line where I call my z score function to preform the math.

import numpy as np
import scipy.stats as stats
import pandas as pd



def calculate_z_score(arr):
  
    mean = np.mean(arr)
    std_dev = np.std(arr)
    z_scores = [(s - mean) / std_dev for s in arr]
    return z_scores

#Tested z-score function on self inputted array of integers/floats and it worked both times.

def gpa(arr):
  for i in range(len(arr)):
    
   if arr   == 'A':
        return 4.0
   elif arr == 'A-':
        return 3.7
   elif arr == 'B+':
        return 3.3
   elif arr == 'B':
        return 3.0
   elif arr == 'B-':
        return 2.7
   elif arr == 'C+':
        return 2.3
   elif arr == 'C':
        return 2.0
   elif arr == 'C-':
        return 1.7
   elif arr == 'D+':
        return 1.3
   elif arr == 'D':
        return 1.0
   elif arr == 'D-':
        return 0.7
   elif arr== 'F':
        return 0.0
   else:
        return 0.0

num = int(input("How many students took your course? : "))
print ("What was the grade for each student?: ")
p=0
convert = []

for i in range(int(num)):
 p+=1
 convert = input(f'Student {p} :')
gpa(convert)  
 

result = calculate_z_score(convert)
print(result)
#End of Code

Admittedly I'm still fairly new to Python but truly any help would be greatly appreciated as I feel stumped. I believe the error is stemming from an issue from trying to convert the array of strings into an array of floating point numbers. I've been specifically getting this Traceback error message where I call the z score function.

Traceback (most recent call last):
  File "main.py", line 92, in <module>
    result = calculate_z_score(convert)
  File "main.py", line 18, in calculate_z_score
    mean = np.mean(arr)
  File "<__array_function__ internals>", line 200, in mean

  File "/home/runner/z-score/venv/lib/python3.10/site-packages/numpy/core/fromnumeric.py", line 3464, in mean
    return _methods._mean(a, axis=axis, dtype=dtype,
  File "/home/runner/z-score/venv/lib/python3.10/site-packages/numpy/core/_methods.py", line 181, in _mean
    ret = umr_sum(arr, axis, dtype, out, keepdims, where=where)
numpy.core._exceptions._UFuncNoLoopError: ufunc 'add' did not contain a loop with signature matching types (dtype('<U1'), dtype('<U1')) -> None

I've tried using different data types and recoding my GPA function to see if I missed anything. I've also been trying to understand the meaning of the error message and from what I can surmise, it may be an issue of being unable to convert an array of objects like strings to numbers. I've tried testing each of the individual piece of the code such as the z-score function and they seem to have work then, but I'm struggling to get it to be applicable in this time. Any advice or tips would be greatly appreciated.

  • The `gpa` function iterates over an array, but it returns on its first iteration, so it just returns a single float. Within that function, you should instead build up a list of numerical results, and return that whole list. It might be better to have two functions in fact: one that takes a single letter grade and returns a single number; and one that takes a list of letter grades, and making use of the first function, returns a list of numbers. – slothrop Apr 17 '23 at 10:15

2 Answers2

0

First it seems you aren't actually saving the converted gpa values to a list. Instead you are overwriting the convert list variable repeatedly.

convert = []

for i in range(int(num)):
 p+=1
 convert_value = input(f'Student {p} :')
convert.append( gpa(convert_value) )

Then once you have a list of values you should be able to z-score them using:

def calculate_z_score(arr):
    return (arr - np.mean(arr)) / np.std(arr)
Sean
  • 524
  • 2
  • 7
  • `gpa` as-is will try to iterate over the individual characters of `convert_value`, so this won't work as intended. – slothrop Apr 17 '23 at 10:26
  • Yes I was trying to essentially convert/assign the inputted letters to predetermined integers. Thank you so much for your assistance. I tested the lines you suggested and got the desired result. Thank you again. – 0ptimusLime Apr 17 '23 at 23:43
0

The problem is that your convert is not an array but a single integer (last value from stdin). This because your gpa function returns only one value, but the argument is intended to be an array.

You can actually change your gpa function into a dictionary, and then convert your mark after reading the input:

import numpy as np

def calculate_z_score(arr):
    return [(s - np.mean(arr))/np.std(arr) for s in arr]

gpa={
    'a':4.0,
    'a-':3.7,
    'b+':3.3,
    'b':3.0,
    'b-':2.7,
    'c+':2.3,
    'c':2.0,
    'c-':1.7,
    'd+':1.3,
    'd':1.0,
    'd-':0.7,
    'f':0
}

num = int(input("How many students took your course? : "))
print ("What was the grade for each student?: ")
convert = []

for i,n in enumerate(range(num)):
    mark=input(f'Student {i+1}: ').lower()
    try:
        convert.append(gpa[mark])
    except KeyError:
        convert.append(0)

result = calculate_z_score(convert)
print(result)
atteggiani
  • 94
  • 4
  • I tried this and it worked. Thank you so much. I'd like to ask more about the enumerate key word and the syntax behind some of the additional changes you suggested, if possible is there any place you'd suggest I go to find that information? Once again thank you so much for the help. – 0ptimusLime Apr 17 '23 at 23:42
  • You can find information about the enumerate built-in here: https://docs.python.org/3/library/functions.html#enumerate What syntax are you interested in learning more about? – atteggiani Apr 19 '23 at 01:21