so previously I created a code that prompts the user to enter 5 different test scores and then to have that list saved to test.txt. the code works wonderful!
this is my code:
scorefile=open('test.txt','w')
for count in range(5):
print('Please enter test scores')
score=input('Test score:')
scorefile.write(str(score)+'%' + '\n')
scorefile.close()
BUT now, i encounter a problem. I have the code to read the file. it works great! but when I try to get the average from the list, all I keep getting is 0.0. I've been reading thru my book about python to figure out how to make this work, but Im seriously stuck now. help?
here is my code:
scorefile=open('test.txt', 'r')
for line in scorefile:
print(line, end='')
score=scorefile
average = sum(score) / 5
print('The test average is', average)
scorefile.close()
This line, score=scorefile doesn't do what you think it does. In fact, it doesn't do anything useful at all.
Perhaps you want:
with open('test.txt') as scorefile:
scores = [int(line.replace('%','')) for line in scorefile]
average = sum(scores) / len(scores)
score=scorefile just assigns the file descriptor to score. It does not actually read the contents and assign them to the score variable as you expected.
You need to read the lines in the file, strip the '%' character, convert each line to an float(since they were percentages I am assuming), sum them up and take the average.
Like this:
with open('input') as in_file:
data = in_file.readlines()
average = sum([float(a.strip('%')) for a in data]) / len(data)
print(average)
[float(a.strip('%')) for a in data] is a short hand notation (also called list comprehension) for doing:
a_list = []
for a in data:
a_list.append(float(a.strip('%')))
Related
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.
Okay, So I´m doing a program that simulates dice rolls and then saves them to a file.
I thought that the easiest option, in my opinion, would be to just save every single iteration of the loop and save the print to the file line by line. But unfortunately, I cannot figure it out.
import random
output=[]
order=0
inpu_t=int(input("Enter the number of simulated throws: "))
f = open('file.txt','w')
figures = (0,)*6
for i in range(inpu_t):
order = order+1
throw = random.randint(1, 6)
figure = figures[throw -1]+1
print(order,'.throw and {}-times fell the number {}.'.format(figure, throw ))
output.append(order)
output.append(figure)
output.append(throw )
figures = figures[:throw -1]+(figure,)+figures[throw :]
print("\n")
with open('file.txt', 'w') as f:
for item in output:
f.write("%s" % item)
for i in range(6):
print('The number {} fell {}-times.'.format(i+1, figures[i]))
Secondly, I thought I could save all the variables to the list and then somehow through some function save it to a file.
output.append(order)
output.append(figure)
output.append(throw )
There I added all the data to the list.
with open('file.txt', 'w') as f:
for item in output:
f.write("%s" % item)
I added it to the file here.
My output in the file is this: "115216314412511"
I don't know how I should do it so that all 3 numbers are would be together in one line like in the code.
print(order,'.throw and {}-times fell the number {}.'.format(figure, throw ))
Append a Carriage Return "/r" with in the for loop after the append throw
hi the better way is to use logging instead to open each time file
read here : How to write to a file, using the logging Python module?
I am trying to make a simple program that takes a text file as input and then prints out a five day temperature forecast from the file. I am having trouble with getting the correct value to print from the delimited string. Any ideas where I went wrong here? My output is attached below.
print("File:")
f = input()
a = open(f, 'r')
b = a.read()
c = b.split(',')
a.close()
count = 1
for i in c:
print("Day {}: {}".format(count, c))
count = count + 1
.close() should be used on the file object.
you should use a.close() to close file.
b is a string resulting of the "read()" executed on the a object (your file)
Once you have that problem solved you can continue trying if your program is working as you expected.
Edit:
Now that you've solved that problem, there's something else I think you should look into.
On your print statement, you ouput the c array, wich comes from splitting the first line of the file, and only the first one. You're not looping through the file lines. That's why you always get the same array as output for each day.
If your goal is to print one number per day, then your code should be:
for i in c:
print("Day {}: {}".format(count, i))
count = count + 1
If your goal is to repeat this process for every line inside the file, then you should do something like:
for line in f:
#your code
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.
Ok, so I'm new to python and I'm currently taking the python for everybody course (py4e).
Our lesson 7.2 assignment is to do the following:
7.2 Write a program that prompts for a file name, then opens that file and reads through the file, looking for lines of the form:
X-DSPAM-Confidence: 0.8475
Count these lines and extract the floating point values from each of the lines and compute the average of those values and produce an output as shown below. Do not use the sum() function or a variable named sum in your solution.
You can download the sample data at http://www.py4e.com/code3/mbox-short.txt when you are testing below enter mbox-short.txt as the file name.
I can't figure it out. I keep getting this error
ValueError: float: Argument: . is not number on line 12
when I run this code (see screenshot): https://gyazo.com/a61768894299970692155c819509db54
Line 12 which is num = float(balue) + float(num) keeps acting up. When I remove the float from balue then I get another which says
"TypeError: cannot concatenate 'str' and 'float' objects on line 12".
Can arguments be converted into floats or is it only a string? That might be the problem but I don't know if it's true and even if it is I don't know how to fix my code after that.
Your approach was not so bad I would say. However, I do not get what you intended with for balue in linez, as this is iterating over the characters contained in linez. What you rather would have wanted float(linez). I came up with a close solution looking like this:
fname = raw_input("Enter file name: ")
print(fname)
count = 0
num = 0
with open(fname, "r") as ins:
for line in ins:
line = line.rstrip()
if line.startswith("X-DSPAM-Confidence:"):
num += float(line[20:])
count += 1
print(num/count)
This is only intended to get you on the right track and I have NOT verified the answer or the correctness of the script, as this should be contained your homework.
I realise this is answered - I am doing the same course and I had the same error message on that exact question. It was caused by the line being read as a non float and I had to read it as
number =float((line[19:26]))
By the way, the Python environment in the course is very sensitive to spaces in strings - I just got the right code and it rejected it since I had ": " and the correct answer was ":" - just spent half an hour on colons.
Just for the sake of it, here is the answer I reached, which has been accepted as the correct one. Hope you got there in the end.
# Use the file name mbox-short.txt as the file name
count = 0
average = 0
filename = input("Enter file name: ")
filehandle = open(filename)
for line in filehandle:
if not line.startswith("X-DSPAM-Confidence:") : continue
line = line.rstrip()
number =float((line[19:26]))
count = count + 1
average = average + number
average = (average / count)
average = float(average)
print("Average spam confidence:",average)
#Take input from user
fname = input("Please inser file name:")
#try and except
try:
fhand = open(fname)
except:
print("File can not be found", fname)
quit()
#count and total
count= 0
total = 0
for line in fhand:
line = line.rstrip()
if not line.startswith("X-DSPAM-Confidence:"):
continue
else:
line = line[20:]
uline = line.upper()
fline = float(uline)
count = count+1
total = total + fline
avr = total / count
print("Average spam confidence:" ,avr )
The short answer to your problem is in fixing the slicing of the string to extract the number.
If you are looking for colon character, ":" to find the floating number,
remember you have to slice the string with +1 added to the slicing. If you do not do that you end up getting-----> : 0.8475
which is not a number.
so, slice the string with +1 added to the starting index of the string and you shall have a fix.