Adding user data into rows python - python

I am banging my head agaisnt a wall trying to figure out something that is simple.
Basically I have a .CSV with names in and test scores e.g.
Brad 4, 5, 7, 7
Dan 3, 6, 2, 7
What I want to do is write code that first all of prints out the tests scores. This bit works fine.
The aspect that I can not get to work is the part were the program reads the names, in the CSV. If the name is present it will append the CSV with the new score at the start. So insert the new value at array position 1.
If the name is not present in the CSV it will add name and then again insert the value at array position 1.
Here is the code that does not work currently, I don't believe it to be complicated however I must be thinking about it wrong.
import csv
def names():
global fn
fn = input("please enter first name \n").title()
namecheck = False
while namecheck == False:
nc = input("you have entered " + fn + " are you sure \n 1) Yes \n 2) No")
if nc == "1":
quiz()
namecheck = True
if nc =="2":
names()
def quiz():
option = input("do you want to print or append? \n 1) Print 2) Append")
if option =="1":
f = open('namelist.csv', 'r')
a = f.read()
print(a)
if option =="2":
score = input("please enter score")
score = int(score)
with open('namelist.csv', 'rt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
for field in row:
if field == fn:
XXXXXXXX <--- this is were I think I am going wrong.
names()

when you declare a def, you have to indent the entire section.
def quiz():
[-->INDENT HERE!] option = input("do you want to print or append? \n 1) Print 2) Append")
[-->INDENT HERE!] rest of def..
#back to main statements..
(Of course I don't mean for you to type "[-->INDENT HERE!]" literally)

Do you have to literally write to the file every time someone adds a new score or a new name? If writing to file at the end of program is an option, I'd suggest collecting all info ahead of time and then writing the data in bulk toward the end..that way you could maintain everything in memory and do the I/O with file in one go, sparing you a lot of file operations and giving you the convenience of working with python data structures such as dicts/sets etc....
If that's not an option...
Looking up names by reading the file is really inefficient as you are reading the entire file just to see if the name is present.
I'd recommend using a dict to store the list of names you've already entered. This way checking the dict to see if the name is present or not is much more efficient...You could try storing the dict with key=name and value=line number on which you entered the name while you wrote to csv.
That way if you found the name in dict, you can go to the particular line and then append your data like this:
Start reading and writing on specific line on CSV with Python
To insert an element in the first position (i am assuming this is after the name), you could do something like:
l = line.split(",")
#assumes first element is the name of the person
l.insert(1, new_score) # 1 is the position you want to insert the data
#then insert this data into a_NEW_CSV file, as writing to same CSV at same line is difficult...
See this for more details: Replace data in csv file using python

Related

How to read the float from a file and display the average in Python

I am trying to convert from string to float. I am pulling the text from a file. Any help or hints would be greatly accepted. I am a newbie on coding. Thanks in advance.
def main():
name =["","","","","",""]
lname = ["","","","","",""]
grade = [0,0,0,0,0]
#total = 0
#count = len(name)
#average = total / count
# for i in range(len(grade)):
# total += grade[i]
#Intro
print("Grades Processing App!\n")
infile = open("gradestest.txt", "r")
for n in range(5):
line = infile.readline()
#split data into 3 fields
name[n], lname[n], grade[n] = line.split(",")
grade[n] = float(grade[n])
#infile.close()
#Display data on screen
print("Name\t\t\tGrade")
print("--------------------")
for i in range(5):
print(name[i], "\t", lname[i], "\t", grade[i])
print('\n')
infile.close()
#for n in range(len(grade)):
#total += grade[n]
# count +1
# print(average)
print('Enter the following student information')
FirstName = input("\tFirst name: ")
LastName = input("\tLast name: ")
Grade = float(input("\tTest grade : "))
infile = open("gradestest.txt", "a")
infile.write(name + "," + lname + "," + float(grade) + "\n")
infile.close()
main()
The problem in your code you can't write float values to file. You can only write string value, you can convert it to float when reading the file.
def main():
print("Grades Processing App!\n")
with open('test.txt') as fp:
data = [line.strip().split(",") for line in fp]
#Display data on screen
print("Name\t\t\tGrade")
print("--------------------")
for name, lname, grade in data:
print(name, "\t", lname, "\t", grade)
grades_avg = sum([float(val[2]) for val in data])/len(data)
print("\nAverage:", grades_avg)
print('\nEnter the following student information')
fname = input("\tFirst name: ")
lname = input("\tLast name: ")
grade = input("\tTest grade : ")
with open("test.txt", "a") as fp:
fp.write(fname + "," + lname + "," + grade + "\n")
main()
Hmmm...so there is quite a bit to discuss I think.
1) First, we note that in python you don't need to allocate memory for your objects. Hence, declaring the size and content of your variables is unnecessary. Python is dynamic, hence one would simply say, "x=[]", to begin a list. and then "x.append(7)" to append a 7 to a list. If you are using ipython (highly recommended) then you can play around with variables on-the-fly and see what they do. For example x.(press tab) will show you all the "methods" available for lists.
2) There are many functions in python that simplify doing repeated tasks. For example, the join method for strings, inserts any string between the sequence of strings your provide. Another example is that open() automatically closes files if the variable isn't used anymore, hence in python you can normally open, read, and close a file in one line.
3) Python highly revolves around iterators that allow you to simplify many many tasks. These include builtins, like sorted, reversed, map, filter, range, etc. It is highly recommended to become familiar with those, as they will greatly enhance your code.
Lets simplify your code a bit:
# Read all lines at once. No need to say 'r', that is the default.
# The file closes automatically when the variable falls out of scope.
lines = open('gradestest.txt').readlines()
# Split each line. You can do it all at once in a list comprehension.
lines = [line.split(',') for line in lines]
# Leaves all the entries alone but the last one. Python can access backwards.
# The line[:-1] means to access everything but the last item as a list.
# The line[-1] means to access the last item (which is grade).
lines = [line[:-1]+[float(line[-1])] for line in lines]
# There are other ways to read your file as well (probably faster).
# Python has a huge library of modules, like the csv module which is for
# opening and reading csv files.
# The join method inserts strings between other strings. The map function
# takes each item in an object and applies the given function to them. Hence,
# map(str,line) turned all the items into a string (including the item you
# made a float earlier.
print("Grades Processing App!\n")
print("Name\t\t\tGrade")
print("--------------------")
print('\n'.join('\t'.join(map(str,line)) for line in lines))
# Not quite sure what this code was for. You don't use your variables
# anywhere. Also you run float(grade) which I think will error, since
# grade is a list. Anyway, I think you meant to append to the file
# some new inputs.
print('Enter the following student information')
FirstName = input("\tFirst name: ")
LastName = input("\tLast name: ")
Grade = float(input("\tTest grade: "))
open('gradestest.txt','a').write(','.join([FirstName,LastName,Grade])+'\n')
Don't think I answered the original question. If you want to find an average in python, there are two builtin commands len() and sum() which count the number of items in a list and add up the items in a list. For example,
grades = [1,2,3,4,5]
average = sum(grades)/len(grades)
I know this is a lot more than you asked for, but since I left some long tips in the comments, I pasted them here with examples.
A tip about files: you can use with open('myfile.txt', 'r') as infile: and put the code that uses the file in that block under it. Once the execution of code leaves that block, the file is reliably closed - even in the case of an exception being thrown.
To address the question in your post, converting text to a float or int value is pretty simple. The only trouble is when the string data isn't in a format that can be converted to an int or float. The exception handling below will make your program a bit more robust and it won't blow up when the conversion fails. But looking at what you had in your code should work.
with open('gradestest.txt', 'r') as infile:
for line_no, line in enumerate(infile):
try:
name, lname, grade = line.split(',')
grade = float(grade)
except ValueError as ve:
print(f"Warning, file format incorrect on line "
f"{line_no + 1}: {ve}")
I added some fault tolerance to the loop that reads in grades. When .split() doesn't produce the right number of items, or float() fails trying to convert a non-numeric string, a ValueError is raised. The except block catches the ValueError and prints a warning about the file format, but the loop can continue to try and process the rest of the file.
Rather than have lists of data that rely on the index to associate different data with the same student, create a Student class that has data members for name and grade. That way you can iterate over the student list rather than iterating over a range of indices.
class Student:
def __init__(self, name, lname, grade=None):
self.name = name
self.lname = lname
self.grade = grade
The above isn't what some may consider a proper implementation of a class because we'll be accessing the data members directly from other code in your program. Since this is a very simple program that's just processing file data, and we only have three pieces of data to manage, we'll flex the coding standards a bit.
Now you have a way to reference grade and student data by attribute name on the student objects. And to be able to grab the list of students at different points in the program, we'll add them to a list.
student_list = []
with open('gradestest.txt', 'r') as infile:
for line_no, line in enumerate(infile):
try:
name, lname, grade = line.split(',')
grade = float(grade)
student_list.append( Student(name, lname, grade) )
except ValueError as ve:
print(f"Warning, file format incorrect on line "
f"{line_no + 1}: {ve}")
Then later in the program when we want to list out the students and their grades:
print(f"{'name':<20} Grade") # Pads 'name' to 20 characters with spaces.
for st in student_list:
print(f"{st.name+' '+st.lname:<20} {st.grade}")
I'm using f-strings to format the text. The text between curly braces is interpreted as Python code and returns strings at the positions in the string where they're at. The :<20 left-aligns and pads the text with spaces.
One last suggestion. This might be a little advanced, suppose you're maintaining student records and want to be able to save the information to a file, then come back to your program later and load your student objects back up with all their information in them, you could use the pickle module for that (although you might also consider a simple database - the sqlite module is pretty good)
Pandas is also a good option if you're working with tabulated student data - it can save its dataframes to file and retrieve them pretty easily.
Anyway, here's pickle:
import pickle
...
# Somewhere in your code...
save_file_y_n = input("Do you want to save student data? ")
if save_file_y_n.lower() in ['y', 'yes']:
file_name = input("Name of file: ")
# Write the Students out to a file.
pickle.dump(student_list, open(file_name, 'wb+'))
...
# Somewhere else in your code - or another script/program..
if load_file_y_n.lower() in ['y', 'yes']:
file_name = input("File name for student records: ")
# Reconstructs the Student objects from the file data
# with their name, lname, grades and any other attributes
# you may have added:
student_list = pickle.load(open(file_name, 'rb'))
print("List of students:")
for st in student_list:
print(f"st.name")
It's always a great idea to back your data up regularly in case the student data file gets somehow corrupted or accidentally deleted. You could even implement some code in your program to save student data in a new file each day and load the latest when the program starts.
A little information on this in case you're curious and not overwhelmed already https://wiki.python.org/moin/UsingPickle
Another option for saving application information is the json module. It can write basic data objects out to a file using plain text. https://docs.python.org/3/library/json.html
And of course you could use CSV (comma separated values) - there's a csv module for that, https://docs.python.org/3/library/csv.html?highlight=csv#module-csv.

Code to print corresponding CSV/list values for car program is not printing anything at all

I have tried to get help on this question all day, but none of the already-asked questions have solved my problem, and any answers I have asked to help me solve this problem have resulted in answers that didn't answer the question.
As it stands now, my program takes the values of MPG ratings represented in a CSV and puts them in a list. These lists represent maximum and minimum MPGs. Once the max/min MPG rating is found is where I get into my problem. I need to be able to print all the cars that have the minimum/maximum MPG value. Ideally, the models should be printed indented under the print statements for the maximum/minimum mileage ratings.
The way the CSV file is done the MPG ratings are in column 9 (index[8]). The make and models are in columns 2 and 3, respectively (index[1] and index[2], respectively). As you'll see in the code, I tried looping through the list and using an if statement to pull the make/model, but when I do that it does not work. I don't know if the files play a part or not, but any help would be appreciated.
# prints welcome screen, asks user what year they want vehicle data for, and asks user for file name to save vehicle data to
print("Welcome to EPA Mileage Calculator")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
while yearChoice != 2008 and yearChoice != 2009:
print("Invalid input, please try again")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
saveResults = input("Enter the filename to save results to: ")
def carData():
if yearChoice == 2008:
fileName = "epaVehicleData2008.csv"
elif yearChoice == 2009:
fileName = "epaVehicleData2009.csv"
fileIn = open(fileName, "r")
fileIn.readline()
minMPG = []
maxMPG = []
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[0] not in ['VANS - PASSENGER TYPE', 'VANS - CARGO TYPE', 'TRUCK', 'MINIVAN - 4WD', 'MINIVAN - 2WD']:
minMPG.append(int(dataList[8]))
maxMPG.append(int(dataList[8]))
maximumMPG = max(maxMPG)
minimumMPG = min(minMPG)
fileOut = open(saveResults, "w")
print("EPA City MPG Calculator", "(" + str(yearChoice) + ")", file=fileOut)
print("---------------------------------", file=fileOut)
print("Maximum Mileage (city):", maximumMPG, file=fileOut)
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[8] == maximumMPG:
print("\t", dataList[1], dataList[2], file=fileOut)
print("Minimum Mileage (city):", minimumMPG, file=fileOut)
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[8] == minimumMPG:
print("\t", dataList[1], dataList[2], file=fileOut)
fileIn.close()
fileOut.close()
def complete():
print()
print("Operation Success! Mileage data has been saved to", saveResults)
print("Thanks, and have a great day!")
def main():
carData()
complete()
main()
You open the input file only once via:
fileIn = open(fileName, "r")
But then you attempt to iterate over the lines in the file three times using that same file handle. You have three of these:
for line in fileIn:
Since you never close and reopen the file, and you don't do anything to seek back to the beginning of the file, the second and third such iterations will never do anything, because you've already reached the end of the file. Using this construct does not cause the file pointer to be rewound and the contents of the file to be iterated over another time.
Since your interesting print statements are in the second and third iterations over the file, which won't produce any new lines (the code in those iteration blocks will never be called), of course your print statements are never called and no output is generated.
To fix your problem, if this is the only thing wrong with your code, just put this line before each of the second and third iterations over the file:
f.seek(0)
to seek back to the beginning of the file and iterate over the contents a second and third time.
To be more efficient, you could read each line once and store it in a list. Then you could iterate over the list each time, and not have to read from the file three times. You could even do the strip and the split just once, making the code even more efficient.
Another small logic error that I see is that you skip one line in your first iteration over the file. I assume that this is to skip a header row at the start of the file. But you don't do this for the second and third iterations, so it seems that if you only add the seek() as I suggested, you'll be trying to process the header line as a data line. This would also be solved by reading the file once into a list. You'd skip the first line of the file while you do this. If you want to leave the code alone other than adding the seek(), you should also skip the first line before the second and third iterations.

WITHOUT using Pandas, how do I analyze CSV data and only extract certain values from certain columns and rows of my CSV file?

I am writing a program that extracts the minimum and maximum MPG rating for cars. The car's information is stored in a CSV file. I believe I wrote the correct min/max functions, however, I wrote it as if I was looping through all of the rows/columns.
We are only supposed to include certain categories of cars for data extraction. The category of a car is the first column of CSV data, which has an index of [0]. The MPG rating I am looping through is in column 10, which has an index of [9].
We are not supposed to include the categories "van", "minivan" or "trucks" in our min/max MPG calculation. Is there a way to exclude based on these strings and loop through the remaining MPGs that are not excluded?
Lastly, once this is accomplished, I am supposed to write these results to a new file. Is there any way I can open the file being written, to check if my code works?
When I try to print the contents of the newly created file (based on user input), I get an error saying that file is not in the directory. Any help would be appreciated.
NOTE: We are not allowed to import Pandas.
Current Code:
print("Welcome to EPA Mileage Calculator")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
while yearChoice != 2008 and yearChoice != 2009:
print("Invalid input, please try again")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
saveResults = input("Enter the filename to to save results to: ")
if yearChoice == 2008:
fileIn = open("epaVehicleData2008.csv", "r")
fileIn.readline()
minMPG, maxMPG = [], []
for line in fileIn:
line = line.strip()
dataList = line.split(",")
minMPG.append(line[9])
print(min(minMPG))
print(max(maxMPG))
if yearChoice == 2009:
fileIn = open("epaVehicleData2009.csv", "r")
fileIn.readline()
minMPG, maxMPG = [], []
for line in fileIn:
line = line.strip()
dataList = line.split(",")
minMPG.append(line[9])
print(min(minMPG))
print(max(maxMPG))
fileIn = open(saveResults, "r")
for line in fileIn:
print(line)
First, you have a bug in the two spots in your code like this:
line = line.strip()
dataList = line.split(",")
minMPG.append(line[9])
In the third line, you're getting the value line[9]. That's the character at index 9 in the line, not the value at index 9 of the list. Do minMPG.append(dataList[9]) instead.
Next, you can check that the vehicle type is not in a specific group using an if statement. Something like
if dataList[9] not in ['van', 'truck', 'minivan']:
minMPG.append(dataList[9])
For your last problem, you haven't saved anything in saveResults yet, or created the file, so it makes sense that you get an error when you try to read it. There are a lot of questions and answers on how to do that. Look to some of those, and ask a separate question if you can't get your code to work.

In Python how to view a specific row based on user input

I'm trying to figure out how to view a specific row in Python for example, I have a contact.csv file and I would like to view their name, email and phone number based on user input.
So, if a user inputs 2, for example, it would display contact 2's information.
Any help would be greatly appreciated,
Thanks.
If you’re just doing this one time, you can keep track of the line numbers:
def view_contacts():
contact_view = int(input("Number: "))
with open (FILENAME) as file:
for linenum, line in enumerate(file);
if linennum == contact_view-1;
print (line, end= "")
print ()
break
Notice that -1, because humans often count 1-based rather than 0-based like Python.
You can make this a little shorter:
def view_contacts():
contact_view = int(input("Number: "))
with open (FILENAME) as file:
for line in itertools.islice(contact_view-1, contact_view):
print (line, end= "")
print ()
But if you’re doing this over and over, you probably just want to read the whole file into memory so you can index it:
with open(FILENAME) as file:
contacts = list(file)
def view_contacts(contacts):
contact_view = int(input("Number: "))
print(contacts[contact_view], end="")
print ()
If the file is too big to read into memory, but looping over it repeatedly is too slow, you could look into linecache, or building your own cache, or consider converting the file into a format that you can index directly, or maybe just using a database that does that for you.

Generated number on python open on notepad?

Basically i have a code which inputs 2 random numbers for strength and skill. These 2 inputs i would like to be saved on a notepad. The number generates a random number for strength and skill and i would like the number to saved on the notepad every time. So when i look back on the notepad it shows the last number which were generated. This is my code so far:
import random
playname1 = str(input("Enter player one name"))
print("Welcome",playname1)
strength1 = random.randint(1,12)
strength2 = random.randint(1,4)
strength3 = (strength1/strength2)
strength4 = round(strength3)
strength5= (10+strength4)
print ("Your strength is...",strength5)
skill1 = random.randint(1,12)
skill2 = random.randint(1,4)
skill3 = (skill1/skill2)
skill4 = round(skill3)
skill5= (10+skill4)
print ("Your skill is...",skill5)
The next part of the code i would like to be the two numbers for strength and skill to be save on a notepad.
the easiest way is
import os
strength5,skill5 =10,20
with open("data.txt") as f:
f.write("%s %s"%(strength5, skill5))
os.startfile("data.txt")
assuming I understand what you mean by "save on notepad" (eg. you dont mean write it down on a sticky note?)
You didn't specify the version of Python you are using, but according to your syntax, I assume you are using Python3? First of all, you don't need to do str(input(...)) - that's already a str.
In Python3, the correct way to write to a file is:
with open('text.txt', 'w') as f:
print('a sentence', file=f) // this will add a new line at the end automatically
// or you can do:
// f.write('a sentence\n')
// since write doesn't add new line automatically, you need to explicitly type \n
Open the file in your initialization.
f = open('output.txt', 'w')
Note that this opens it in write mode so all previous data are erased. If you want to append use
f = opr('output.txt', 'a')
Now just write the text data
datatxt = ' '.join(str(strength5), str(skill5))
f.write(datatxt)
After you completely finish
f.close()

Categories

Resources