1

I have an CSV file, which has the current format below.

A two row example of this would be:

first_Name  last_Name   test1   test2   test3   test4
Alex        Brian       11      17      13      24
Pete        Tong        19      14      12      30

Now my current code does not work, Simply put I am not sure if I am on the right track. My current code:

def grader(test1, test2, test3, finalExam):
    first = test1 * .20
    second = test2 * .20
    third = test3 * .20
    fourth = finalExam *.40
    finalGrade = first + second + third + fourth
    return finalGrade

def gradeScores(FinalGrade):
    if FinalGrade >= 90 and FinalGrade <= 100:
        return("You received an A")

    elif FinalGrade >= 80 and FinalGrade < 90:
        return("You received a B")

    elif FinalGrade >= 70 and FinalGrade < 80:
        return("You received a C")

    elif FinalGrade >= 60 and FinalGrade < 70:
        return("You received a D")

    else:
        return("Sorry, you received an F")

I also have this line of code which is to read the CSV file, and displays in the output window.

with open("studentGradeFrom.csv") as csvfile:
    readFile = csv.reader(csvfile, delimiter=",", quotechar="¦")
    for row in readFile:
        print(row)

However since I am new to Python, I am looking for help to create a python script, that will look at the results and do a calculation which will tell me if the student has passed or failed. I would like this to be done in a separate file. So I am guessing that I will need to read and write to a different CSV file, to show if a student has failed or has an overall passing percentage.

with open("studentGradeTo.csv", 'w') as avg: #used to write to after the calculation is complete
    loadeddata = open("studentGradeFrom.csv", 'r') #used to read the data from the CSV before calculation.
    writer=csv.writer(avg)
    readloaded=csv.reader(loadeddata)
    listloaded=list(readloaded)

Now my question: How would I go about doing this, from looking at data from one file which roughly 50 different students. While not changing the read CSV with the student grades, and only changing the CSV file which shows passing or failing grades. Any help would be appreciated.

Edit: I forgot to mention that the first test would be work 20% of the final grade, the same with the second test and third test. these three totalling to 60% of final grade. While the fourth test is worth 40% of the final grade.

martineau
  • 119,623
  • 25
  • 170
  • 301
Amir Shaw
  • 135
  • 1
  • 11
  • What exactly do you want the output file to look like? Student names and "You received an F" in separate columns? – Brad Solomon Feb 17 '18 at 16:31
  • Also, consider using the [pandas](http://pandas.pydata.org/pandas-docs/stable/) library for this, which would allow you to do this flexibly in about 5 lines of code. [`pd.cut`](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.cut.html) will make grade-binning easy – Brad Solomon Feb 17 '18 at 16:31
  • @BradSolomon this is correct. Simple their name and if they have passed, which grade. If they have failed then they have received an F. – Amir Shaw Feb 17 '18 at 16:34
  • Is there a possible way to do it without any other modules, except importing csv? – Amir Shaw Feb 17 '18 at 16:39
  • Sure. https://stackoverflow.com/q/19575456/7954504 – Brad Solomon Feb 17 '18 at 16:46
  • Your delimiter is declared as a `,` and your file is tab or space delimited -- difficult to tell on here. – hd1 Feb 17 '18 at 16:49
  • @hd1 this was only done so the readers of this question would better understand what I am trying to portray. Also just a copy of the csv data. This is raw data, and not data being output by py command. – Amir Shaw Feb 17 '18 at 16:50
  • People trying to answer your question need the real input so they can test their code. – martineau Feb 17 '18 at 16:54
  • What is the current output, that u are gettng? – user5722540 Feb 17 '18 at 16:55
  • @user5722540 At the moment nothing, I am not sure how I go about linking columns of test data (test1,test2,test3,final test) to calculate the percentage needed for the calculation. test 1 = * .20 test 2 = * .20 test 3 = * .20 final test= * .40. then i will have a finalcalculationgrade which will be a sum of all the graded marks, which will give me a percentage. calculating a passing or a failing grade. – Amir Shaw Feb 17 '18 at 17:13

2 Answers2

1

Here is a quick example of the concepts using only the csv library (you could certainly optimize a lot of this, but it should work for the example).

import csv

student_grades = []

# First open up your file containing the raw student grades
with open("studentGradeFrom.csv", "r") as file:
    # Setup your reader with whatever your settings actually are
    csv_file = csv.DictReader(file, delimiter=",", quotechar='"')

    # Cycle through each row of the csv file
    for row in csv_file:
        # Calculate the numerical grade of the student
        grade = grader(
            int(row["test1"]),
            int(row["test2"]),
            int(row["test3"]),
            int(row["test4"])
        )

        # Calculate the letter score for the student
        score = gradeScores(grade)

        # Assemble all the data into a dictionary
        # Only need to save fields you need in the final output
        student_grades.append({
            "first_name": row["first_name"],
            "last_name": row["last_name"],
            "test1": row["test1"],
            "test2": row["test2"],
            "test3": row["test3"],
            "test4": row["test4"],
            "grade": grade,
            "score": score
        })

# Open up a new csv file to save all the grades
with open("studentGradeFrom.csv", "w", newline="") as file:
    # List of column names to use as a header for the file
    # These will be used to match the dictionary keys set above
    # Only need to list the fields you saved above
    column_names = [
        "first_name", "last_name", "test1", "test2", "test3",
        "test4", "grade", "score"
    ]

    # Create the csv writer, using the above headers
    csv_file = csv.DictWriter(file, column_names)

    # Write the header
    csv_file.writeheader()

    # Write each dictionary to the csv file
    for student in student_grades:
        csv_file.writerow(student)

You would need to fine tune this to your exact requirements, but it will hopefully get you going in the right direction. Most of this is documented in the official documentation if you need a specific reference: https://docs.python.org/3.6/library/csv.html.

Studybuffalo
  • 399
  • 4
  • 8
0

This kind of task is suited for the pandas library.

Here is one solution, which is adaptable should your requirements change.

import pandas as pd

df = pd.read_csv('studentGradeFrom.csv')

#   first_Name last_Name  test1  test2  test3  test4
# 0       Alex     Brian     11     17     13     24
# 1       Pete      Tong     19     14     12     30

boundaries = {(90, 100.01): 'A',
              (80, 90): 'B',
              (70, 80): 'C',
              (60, 70): 'D',
              (0, 60): 'F'}

def grade_calc(x, b):
    return next((v for k, v in b.items() if k[0] <= x <= k[1]), None)

df['FinalMark'] = 0.2*df['test1'] + 0.2*df['test2'] + 0.2*df['test3'] + 0.4*df['test4']
df['FinalGrade'] = df['FinalMark'].apply(grade_calc, b=boundaries)

#   first_Name last_Name  test1  test2  test3  test4  FinalMark FinalGrade
# 0       Alex     Brian     11     17     13     24       17.8          F
# 1       Pete      Tong     19     14     12     30       21.0          F

df.to_csv('studentGradeTo.csv', index=False)
jpp
  • 159,742
  • 34
  • 281
  • 339