I've got a computing project to do for school where a text document is read and the person who spent the most time excercising on each intensity.When it is run the variables don't change and it is still showing that the top score is 0, if anyone could help show me where i've gone wrong that would be great,
thanks!
The text document looks like this:
NeQua,High,Running,5,Swimming,40,Aerobics,40,Football,20,Tennis,10
ImKol,Moderate,Walking,40,Hiking,0,Cleaning,40,Skateboarding,30,Basketball,20
YoTri,Moderate,Walking,20,Hiking,30,Cleaning,40,Skateboarding,20,Basketball,40
RoDen,High,Running,20,Swimming,20,Aerobics,40,Football,30,Tennis,50
etc.
moderate_top_player = ""
high_top_player = ""
moderate_top_score = 0
high_top_score = 0
# open file, with will automatically close it for you
with open("text_documents/clientRecords.txt") as f:
for line in f:
ID,intensity,activity_1,time_1,activity_2,time_2,activity_3,time_3,activity_4,time_4,activity_5,time_5 = line.split(",")
client_score = int(time_1) + int(time_2) + int(time_3) + int(time_4) + int(time_5)
if intensity == "high" and client_score > high_top_score:
high_top_score = int(client_score)
high_top_player = str(ID)
elif intensity == "moderate" and client_score > moderate_top_score:
moderate_top_score = client_score
moderate_top_player = ID
print(moderate_top_player,"worked",moderate_top_score,"minutes on moderate intensity")
print(high_top_player,"worked",high_top_score,"minutes on high intensity")
I've taken the liberty of renaming some of your variables and using the csv module from the Python standard library to read in the text file instead of manually splitting lines based on commas.
That said, the problem is pretty straight forward to fix. Your data set clientRecords.txt uses capitalized strings for intensity (e.g. High, Moderate) but in your conditional you are comparing against lowercase strings. High == high returns False so the body of the if and the elif blocks are never executed.
import csv
moderate_top_player = ""
high_top_player = ""
moderate_top_score = 0
high_top_score = 0
with open('text_documents/clientRecords.txt', 'rb') as f:
reader = csv.reader(f)
for row in reader:
player_id, intensity, a1, t1, a2, t2, a3, t3, a4, t4, a5, t5 = row
client_score = int(t1) + int(t2) + int(t3) + int(t4) + int(t5)
intensity = intensity.lower()
if intensity == 'high' and client_score > high_top_score:
high_top_score = client_score
high_top_player = player_id
elif intensity == 'moderate' and client_score > moderate_top_score:
moderate_top_score = client_score
moderate_top_player = player_id
print moderate_top_player, moderate_top_score
print high_top_player, high_top_score
The important line:
intensity = intensity.lower()
Alternatively, instead of converting the read-in intensity to lower case, you could change your if statements to test against High instead of high and Moderate instead of moderate. Either way will do.
Related
I am creating a program for counting coins and I want to create a mechanism which essentially scans a specifically written text file and is able to calculate whether it has been falsely counted but also will replace the ending segment of the line with either Y for Yes or N for No.
The txt file reads as such:
Abena,5p,325.00,Y
Malcolm,1p,3356.00,Y
Jane,£2,120.00,Y
Andy,£1,166.25,N
Sandip,50p,160.00,Y
Liz,20p,250.00,Y
Andy,20p,250.00,Y
Andy,50p,160.00,Y
Jane,£1,183.75,N
Liz,£,179.0,N
Liz,50p,170.0,N
Jane,50p,160.0,Y
Sandip,£1,183.0,N
Jane,£2,132.0,N
Abena,1p,3356.0,N
Andy,2p,250.0,N
Abena,£1,175.0,Y
Malcolm,50p,160.0,Y
Malcolm,£2,175.0,N
Malcolm,£1,175.0,Y
Malcolm,1p,356.0,Y
Liz,20p,250.0,Y
Jane,£2,120.0,Y
Jane,50p,160.0,Y
Andy,£1,175.0,Y
Abena,1p,359.56,N
Andy,5p,328.5,N
Andy,£2,108.0,N
Malcolm,£2,12.0,N
as you can see every line is split into 4 segments, I want the fileinput to be able to replace the fourth segment within the specified line.
My program (all the relevant things to see right now) is as follows:
class Volunteer:
def __init__(self, name, coin_type, weight_of_bag, true_count):
self.name = name
self.coin_type = coin_type # a function allowing me to class the data
self.weight_of_bag = weight_of_bag
self.true_count = true_count
just a simple object system to make things easier for later
with open("CoinCount.txt", "r", encoding="'utf-8'") as csvfile:
volunteers = []
for line in csvfile:
volunteers.append(Volunteer(*line.strip().split(',')))
just to create a list as well as an object for easier calculations
def runscan():
with open("CoinCount.txt", "r+", encoding='utf-8') as csvfile:
num_lines = 0
for line in csvfile:
num_lines = num_lines + 1
i = 0
while i < num_lines:
ct = (volunteers[i].coin_type)
wob = float(volunteers[i].weight_of_bag)
if ct == ("£2" or "2"):
accurate_weight = float(12.0)
limit = 10
bag_value = 10 * 12
elif ct == ("£1" or "1"):
accurate_weight = float(8.75)
limit = 20
bag_value = 20 * 8.75
elif ct == "50p":
accurate_weight = float(8)
limit = 20
bag_value = 20 * 8
elif ct == "20p":
accurate_weight = float(5)
limit = 50
bag_value = 5 * 50
elif ct == "10p":
accurate_weight = float(6.5)
limit = 50
bag_value = 6.5 * 50
elif ct == "5p":
accurate_weight = float(3.25)
limit = 100
bag_value = 3.25 * 100
elif ct == "2p":
accurate_weight = float(7.12)
limit = 50
bag_value = 50 * 7.12
elif ct == "1p":
accurate_weight = float(3.56)
limit = 100
bag_value = 3.56 * 100
number_of_bags = wob / bag_value
print("Number of bags on this is" + str(number_of_bags))
import fileinput
line = line[i]
if number_of_bags.is_integer():
with fileinput.FileInput('CoinCount.txt',inplace=True) as fileobj:
for line in fileobj:
x = line.split(',')
for w, word in enumerate(x):
if w == 3 and word == 'N':
print(line[i].replace('N', 'Y'), end='')
i = i + 1
else:
i = i + 1
else:
with fileinput.FileInput('CoinCount.txt',inplace=True) as fileobj:
for line in fileobj:
x = line.split(',')
for w, word in enumerate(x):
if w == 3 and word == 'Y':
print(line[i].replace('Y', 'N'), end='')
i = i + 1
else:
i = i + 1
and finally the thing Im having issues with, the scan function.
the issue is specifically within the last few lines of code here (the replacement part):
import fileinput
if number_of_bags.is_integer():
target, replacement = ('N', 'Y')
else:
target, replacement = ('Y', 'N')
with fileinput.FileInput('CoinCount.txt', inplace=True) as fileobj:
for i, line in enumerate(fileobj):
words = line.rstrip().split(',')
if line.words[3] == target:
line.words[3] = replacement
print(','.join(words))
i = i + 1
f = fileobj.lineno() # Number of lines processed.
print(f'Done, {f} lines processed')
I basically have created a function which goes down each line and calculates the next line down until there aren't anymore lines, the issue with the last part is that I am unable to replace the actual txt file, If I were to run this program right now the result would be a completely blank page. I know that the fix is most likely a simple but tricky discovery but It is really bothering me as this is all that is needed for my program to be complete.
I understand the majority of the coding used but I am very new to fileinput, I want to be able to go from each line and replace the final segment if the segments name (i.e "Y" or "N") given is inaccurate to the actual legitimate segment name as Y is for true and N is for false. Please help, I tried to make sure this question was as easily understandable as possible, please make your example relatable to my program
As far as I understood, the problem is whether the calculation of the weight is correct or not. So just create another file instead of using fileinput. Do you really need it ?
test.csv
Abena,5p,325.00,Y
Malcolm,1p,3356.00,Y
Read the csv and assign some header names
Remove the last column, we don't care if it's correct or not, we will calculate the result anyways
Gather your calculation function in one method, we will apply this to every row
Apply function to every row, if it's correct write "Y" else write "N"
Truncate the whole file and write it over
import pandas as pd
with open("test.csv", "r+") as f:
df = pd.read_csv(f, names=["name", "coin", "weight", "res"])
del df["res"]
def calculate(row):
if row["coin"] == "5p":
return "Y" if 3.25 * 100 == row["weight"] else "N"
elif row["coin"] == "1p":
return "Y" if 3.56 * 100 == row["weight"] else "N"
df["res"] = df.apply(lambda row: calculate(row), axis=1)
f.seek(0)
f.truncate()
df.to_csv(f, index=False, header=False)
test.csv
Abena,5p,325.0,Y
Malcolm,1p,3356.0,N
I've built a function to cut the extraneous garbage out of text entries. It uses an array slicer. I now need to reconcile the lines that've been removed by my cleanup function so all the lines_lost + lines_kept = total lines. Source code below:
def header_cleanup(entry_chunk):
# Removes duplicate headers due to page-continuations
entry_chunk = entry_chunk.replace("\r\n\r\n","\r\n")
header = lines[1:5]
lines[:] = [x for x in lines if not any(header == x for header in headers)]
lines = headers + lines
return("\n".join(lines))
How could I count the lines that do not show up in lines after the slice/mutation, i.e:
original_length = len(lines)
lines = lines.remove_garbage
garbage = lines.garbage_only_plz
if len(lines) + len(garbage) == original_length:
print("Good!")
else:
print("Bad! ;(")
Final answer ended up looking like this:
def header_cleanup(entry_chunk):
lines = entry_chunk.replace("\r\n\r\n","\r\n")
line_length = len(lines)
headers = lines[1:5]
saved_lines = []
bad_lines = []
saved_lines[:] = [x for x in lines if not any(header == x for header in headers)]
bad_lines[:] = [x for x in lines if any(header == x for header in headers)]
total_lines = len(saved_lines) + len(bad_lines)
if total_lines == line_length:
print("Yay!")
else:
print("Boo.")
print(f"{rando_trace_info}")
sys.exit()
final_lines = headers + saved_lines
return("\n".join(final_lines))
Okokokokok - I know you're thinking: that's redundant, but it's required. Open to edits after solution for anything more pythonic. Thanks for consideration.
Don't reuse the lines variable, use a different variable, so you can get the garbage out of the original lines.
clean_lines = remove_garbage(lines)
garbage = garbage_only(lines)
if len(clean_lines) + len(garbage) == len(lines):
print("Good!")
else:
print("Bad!")
You might want to have a single function that returns both:
clean_lines, garbage = filter_garbage(lines)
import datetime
with open("fine.txt","r") as f, open("fine1.txt","a") as fine1:
lines = f.read().split("\n")
for i in range(2):
var = input("reg : ") # registration number(reg_num)
enter = input('Time entered camera 1(24hrs)in the format HH:MM:SS: ')
ext = input('Time enterd camera 2 (24hrs)in the format HH:MM:SS : ')
total_time = '%H:%M:%S'
enter_time = datetime.datetime.strptime(enter, total_time)
ext_time = datetime.datetime.strptime(ext, total_time)
if enter_time > ext_time:
ext_time += datetime.timedelta(hours=24)
t_diff = ext_time - enter_time
time = t_diff.total_seconds() / 3600
speed = 1 / time
reg = var[0:1].isalpha() and var[2:3].isdigit() and var[4].isspace() and var[5:7].isalpha() and var.isupper()
if reg == True:
for i, line in enumerate(lines):
if var in line:
num = int("{}".format(i))
var = f.read()
name = (var[num]) #the problem
print(name)
address = (var[num + 0])
if speed > 70:
print("ovrspeeding", (var[num + 0]))
fine1.write(name+address+speed+"\n")
The whole code had to inputted, otherwise you will not understand what i am trying to do.
fine.txt is a file that has already been made and looks like:
reg_num1 aaaaaaaaaaaaaaaaaaa
reg_num2 bbbbbbbbbbbbbbbbbbb
reg_num3 ccccccccccccccccccc
this code takes in inputs of the registration number(e.g. AA01 SSS) and 2 time formats (which will later be used to calculate the speed). i want this code to find the line in fine.txt that have the registration number i inputted and if that vehicle is overspeeding(speed >70mph)the whole line needs to be appended into the file fine1.txt.
the problem is that when i run the code the error massage states that:
name = (var[num])
IndexError: string index out of range
i dont what this means, so can you help me with this.
All of this code functions perfectly when run alone. However, when i choose the standings option after i have run the new and fixture option the code throws an error. Any assistance on this matter would be greatly appreciated.
main():
print ("Welcome to Tournament Tracker")
print ("would you like to begin a new tournament (new), input the results of a fixture (fixture) or view the tournament standings(standings)")
#allows the user to choose from several options including accesing an old tournament or creating a new one.
response = input()
#defines a variable "response" which will be checked against predefined, suggested responses using a slection statement
if response == "new":
#selection statment checks if variable "response" is = "new" and, if true, executes the following code
print ("enter in the name of the tournament")
tournamentName = input()
#creates variable tournamentName and sets it to user input
with open(tournamentName + ".txt",mode="w",encoding = "utf-8") as tournamentfile:
pass
#creates file "tournamentName + ".txt""
print ("enter in the number of teams in the tournament")
numberOfTeams = int(input())
allPoints = int(0)
awayPoints = int(0)
#initalises the two variables "allPoints" and "awayPoints" to be written to text file
counter = int(0)
#initialises temporary variable counter to be used for iteration
while counter < numberOfTeams:
# while loop executes the following code unless the condition "counter" < "number of teams"
counter = counter +1
#one is added to the counter to ensure that the condition "counter" < "number of teams" will be met
print ("enter in the name of team {0}".format(counter))
teamName = input()
#asks the user for the name of each team linked to variable counter
print ("Team {0} is {1}".format(counter,teamName))
with open(teamName + "Points.txt", mode="w",encoding="utf-8") as allPointsfile:
allPointsfile.write(str(allPoints))
#creates a txt file based on the variable "teamName", with "Points.txt" appended to it,
#inputted by the user and writes the variable "allPoints" to it
with open(teamName + "AwayPoints.txt", mode = "w",encoding = "utf-8") as awayPointsfile:
awayPointsfile.write(str(awayPoints))
#creates a txt file based on the variable "teamName", with "AwayPoints.txt" appended to it,
#inputted by the user and writes the variable "awayPoints" to it
with open(tournamentName + ".txt", mode="a",encoding="utf-8") as tournamentfile:
tournamentfile.write(teamName +"\n")
tournamentfile.write(str(allPoints) + "\n")
tournamentfile.write(str(awayPoints) + "\n")
#creates a txt file based on the variable "tournamentName", with ".txt" appended to it,
#inputted by the user and writes the variables "teamName", "allPoints" and "awayPoints" to it,
#each on a new line
print("You may now add the results of fixtures")
main()
#informs the user that the next recommended option should be to input the results of a fixture
#and then calls the main function to give the user access to the all the options again
elif response == "fixture":
#selection statment checks if variable "response" is = "fixture" and, if true,then executes the following code
print ("enter in the name of the tournament")
tournamentName = input()
print ("enter in the name of the first (home) team")
teamOne = str(input())
print ("enter in the name of the second (away) team")
teamTwo = str(input())
print ("enter in the number of goals scored by the first team in their home fixture")
teamOneScore = input()
print("enter in the number of goals scored by the second team in the same fixture")
teamTwoScore = input()
#initialises variables "tournamentName", "teamOne", "teamOne", "teamOneScore" and "teamTwoScore"
if teamOneScore > teamTwoScore:
#selection statment checks if the variable "teamOneScore" > "teamTwoScore" and if true, executes the following code
with open(teamOne + "Points.txt", mode="r",encoding="utf-8") as allTeamOnePointsfile:
allTeamOnePoints = allTeamOnePointsfile.read()
if allTeamOnePoints == '':
allTeamOnePoints = 0
allTeamOnePoints = int(allTeamOnePoints) + int(3)
#opens the file " teamOne (variable) + "Points.txt"" in read mode and reads the file. If statement checks if the file is empty
#and sets the value read, defined as "allTeamOnePoints" to 0 to avoid an error. Then adds 3 to "allTeamOnePoints"
with open(teamOne + "Points.txt", mode="w",encoding="utf-8") as allTeamOnePointsfile:
allTeamOnePointsfile.write(str(allTeamOnePoints))
#opens the file " teamOne (variable) + "Points.txt"" in write mode and writes the variable "allTeamOnePoints" to the file.
print("{0} now has {1} points".format(teamOne,allTeamOnePoints))
#outputs the team name and the total number of points that team has
with open(teamTwo + "Points.txt", mode="r",encoding="utf-8") as allTeamTwoPointsfile:
allTeamTwoPoints = allTeamTwoPointsfile.read()
if allTeamTwoPoints == '':
allTeamTwoPoints = 0
#opens the file " teamTwo (variable) + "Points.txt"" in read mode and reads the file. If statement checks if the file is empty
#and sets the value read, defined as "allTeamTwoPoints" to 0 to avoid an error.
print("{0} now has {1} points".format(teamTwo,allTeamTwoPoints))
#outputs the total points for teamTwo
with open(tournamentName + ".txt", mode = "r", encoding = "utf-8") as tournamentFile:
tournamentList1 = tournamentFile.readlines()
tournamentList = [elem.strip("\n")for elem in tournamentList1]
#open the file "tournamentName (variable) + ".txt"" and reads it, with each line defined as a different element of an array
#then strips the ""\n"" from the end of each element and defines the variable "tournamentList"
index = 0
#initialises temporary variable "index"
noOfTeams = int(len(tournamentList))
#initialises variable "noOfTeams" as the length of the arrray "tournamentList"
while index < noOfTeams:
#while loop checks if temporary variable "index" < "noOfTeams"
if teamOne == tournamentList[index]:
tournamentList[index]= teamOne
tournamentList[index+1] = allTeamOnePoints
index = index +1
#selection statement checks if the variable "teamOne" is equal to the index'th element of the array "tournamentList"
#sets variable "teamOne" to the index'th element of array "tournamentList" if the previous condition is true
#sets variable "allTeamOnePoints" to the index'th element of array "tournamentList" if the previous condition is true
#adds 1 to index to allow for iteration
elif teamOne != tournamentList[index]:
index = index +1
#selection statement checks if the variable "teamOne" is equal to the index'th element of the array "tournamentList"
#adds 1 to index to allow for iteration
index2 = 0
#initialises temporary variable "index"
while index2 < noOfTeams:
if teamTwo == tournamentList[index2]:
tournamentList[index2] = teamTwo
tournamentList[index2+1] = allTeamTwoPoints
index2 = index2 +1
#selection statement checks if the variable "teamTwo" is equal to the index2'th element of the array "tournamentList"
#sets variable "teamTwo" to the index'th element of array "tournamentList" if the previous condition is true
#sets variable "allTeamTwoPoints" to the index'th element of array "tournamentList" if the previous condition is true
#adds 1 to index2 to allow for iteration
elif teamTwo != tournamentList[index2]:
index2 = index2 +1
#selection statement checks if the variable "teamTwo" is equal to the index'th element of the array "tournamentList"
#adds 1 to index2 to allow for iteration
with open(tournamentName + ".txt", mode = "w", encoding = "utf-8") as tournamentFile:
for counter in range (len(tournamentList)):
#for loop executes the following code the once for each element in array "tournamentList"
tournamentFile.write(str(tournamentList[counter]) + "\n")
#writes variable "tournamentList" to "tournamentName + ".txt"" using for loop
main()
#calls back the function "main()"
elif teamOneScore == teamTwoScore:
#the following code is very similar to the above code. Please see above code for documentation.
with open(teamOne + "Points.txt", mode="r",encoding="utf-8") as allTeamOnePointsfile:
allTeamOnePoints = allTeamOnePointsfile.read()
if allTeamOnePoints == '':
allTeamOnePoints = 0
allTeamOnePoints = int(allTeamOnePoints) + int(1)
with open(teamOne + "Points.txt", mode="w",encoding="utf-8") as allTeamOnePointsfile:
allTeamOnePointsfile.write(str(allTeamOnePoints))
print("{0} now has {1} points".format(teamOne,allTeamOnePoints))
with open(teamTwo + "Points.txt", mode="r",encoding="utf-8") as allTeamTwoPointsfile:
allTeamTwoPoints = allTeamTwoPointsfile.read()
if allTeamTwoPoints == '':
allTeamTwoPoints = 0
allTeamTwoPoints = int(allTeamTwoPoints) + int(1)
with open(teamTwo + "Points.txt", mode="w",encoding="utf-8") as allTeamTwoPointsfile:
allTeamTwoPointsfile.write(str(allTeamTwoPoints))
print("{0} now has {1} points".format(teamTwo,allTeamTwoPoints))
with open(teamTwo + "AwayPoints.txt",mode = "r",encoding="utf-8") as awayPointsfile:
awayPoints = awayPointsfile.read()
if awayPoints == '':
awayPoints = 0
awayPoints = int(awayPoints) + int(1)
with open(teamTwo + "AwayPoints.txt",mode = "w",encoding="utf-8") as awayPointsfile:
awayPointsfile.write(str(awayPoints))
with open(tournamentName + ".txt", mode = "r", encoding = "utf-8") as tournamentFile:
tournamentList1 = tournamentFile.readlines()
tournamentList = [elem.strip("\n")for elem in tournamentList1]
index = 0
noOfTeams = int(len(tournamentList))
while index < noOfTeams:
if teamOne == tournamentList[index]:
tournamentList[index]= teamOne
tournamentList[index+1] = allTeamOnePoints
index = index+1
elif teamOne != tournamentList[index]:
index = index +1
index2 = 0
while index2 < noOfTeams:
if teamTwo == tournamentList[index2]:
tournamentList[index2] = teamTwo
tournamentList[index2+1] = allTeamTwoPoints
tournamentList[index2+2] = awayPoints
index2 = index2+1
elif teamTwo != tournamentList[index]:
index2 = index2 +1
with open(tournamentName + ".txt", mode = "w", encoding = "utf-8") as tournamentFile:
for counter in range (len(tournamentList)):
tournamentFile.write(str(tournamentList[counter]) + "\n")
print (tournamentList)
main()
elif teamOneScore < teamTwoScore:
#the following code is very similar to the above code. Please see above code for documentation.
with open(teamTwo + "Points.txt", mode="r",encoding="utf-8") as allTeamTwoPointsfile:
allTeamTwoPoints = allTeamTwoPointsfile.read()
if allTeamTwoPoints == '':
allTeamTwoPoints = 0
allTeamTwoPoints = int(allTeamTwoPoints) + int(3)
with open(teamTwo + "Points.txt", mode="w",encoding="utf-8") as allTeamTwoPointsfile:
allTeamTwoPointsfile.write(str(allTeamTwoPoints))
print("{0} now has {1} points".format(teamTwo,allTeamTwoPoints))
with open(teamTwo + "AwayPoints.txt",mode = "r",encoding="utf-8") as awayPointsfile:
awayPoints = awayPointsfile.read()
if awayPoints == '':
awayPoints = 0
awayPoints = int(awayPoints) + int(3)
with open(teamTwo + "AwayPoints.txt",mode = "w",encoding="utf-8") as awayPointsfile:
awayPointsfile.write(str(awayPoints))
with open(teamOne + "Points.txt", mode="r",encoding="utf-8") as allTeamOnePointsfile:
allTeamOnePoints = allTeamOnePointsfile.read()
if allTeamOnePoints == '':
allTeamOnePoints = 0
print("{0} now has {1} points".format(teamOne,allTeamOnePoints))
with open(tournamentName + ".txt", mode = "r", encoding = "utf-8") as tournamentFile:
tournamentList1 = tournamentFile.readlines()
tournamentList = [elem.strip("\n")for elem in tournamentList1]
index = 0
noOfTeams = int(len(tournamentList))
while index < noOfTeams:
if teamOne == tournamentList[index]:
tournamentList[index]= teamOne
tournamentList[index+1] = allTeamOnePoints
index = index+1
elif teamOne != tournamentList[index]:
index = index +1
index2 = 0
while index2 < noOfTeams:
if teamTwo == tournamentList[index2]:
tournamentList[index2] = teamTwo
tournamentList[index2+1] = allTeamTwoPoints
tournamentList[index2+2] = awayPoints
index2 = index2 + 1
elif teamTwo != tournamentList[index2]:
index2 = index2 +1
with open(tournamentName + ".txt", mode = "w", encoding = "utf-8") as tournamentFile:
for counter in range (len(tournamentList)):
tournamentFile.write(str(tournamentList[counter]) + "\n")
print (tournamentList)
main()
elif response == "standings":
#selection statment checks if variable "response" is = "fixture" and, if true,then executes the following code
results()
def results():
print ("enter in the name of the tournament you would like to access")
tournamentName1 = input()
#creates variable "tournamentName" and sets it equal to user input
with open (tournamentName1 + ".txt", mode = "r", encoding = "utf-8") as tournamentFile:
tournamentTeam1 = tournamentFile.readlines()[::3]
tournamentTeams1 = [elem.strip("\n")for elem in tournamentTeam1]
#opens the file "tournamentName + ".txt"" and reads every third line into a list. Then strips ""\n"" from every element
#defines the variable "tournamentTeams" as an array of al teams in the tournament
with open (tournamentName1 + ".txt", mode = "r", encoding = "utf-8") as tournamentFile:
tournamentPoint1 = tournamentFile.readlines()[1::3]
tournamentPoints1 = [elem.strip("\n")for elem in tournamentPoint1]
#opens the file "tournamentName + ".txt"" and reads every third line starting from the second element
#into a list. Then strips ""\n"" from every element
#defines the variable "tournamentPoints" as an array with all the total points for each team
with open (tournamentName1 + ".txt", mode = "r", encoding = "utf-8") as tournamentFile:
tournamentAwayPoint1 = tournamentFile.readlines()[2::3]
tournamentAwayPoints1 = [elem.strip("\n")for elem in tournamentAwayPoint1]
#opens the file "tournamentName + ".txt"" and reads every third line starting from the third element
#into a list. Then strips ""\n"" from every element
#defines the variable "tournamentAwayPoints" as an array with all the total away points for each team
order = []
#defines temporary array order as an empty array
pos = 0
#defines temporary variable "pos" as equal to 0
for count in range(len(tournamentTeams1)):
order.append(count)
#creates an array of indexes of the teams
for count in range(len(tournamentTeams1)-1):
if (tournamentPoints1[order[pos]] < tournamentPoints1[order[pos+1]]):
#compares the scores of two consecutive teams and switches them
temp = order[pos]
#temporary variable stores the index of the team
order[pos] = order[pos+1]
order[pos+1] = temp
#switches the order of the teams
elif (tournamentPoints1[order[pos]] == tournamentPoints1[order[pos+1]] and tournamentAwayPoints1[order[pos]] <tournamentAwayPoints1[order[pos+1]]):
#if the score is equal, we compare the away score
temp = order[pos]
order[pos] = order[pos+1]
order[pos+1] = temp
#same logic as prior
pos = pos +1
#adds 1 to variable "pos" in order to allow for iteration
index3 = 0
#defines temporary variable index as equal to 0
print()
for count in range(len(order)):
index3 = index3 + 1
print('{0}: {1} (score {2}) (away score {3})'.format(index3,tournamentTeams1[order[count]],tournamentPoints1[order[count]],tournamentAwayPoints1[order[count]]))
print("Congratulations to team {0} for winning the tournament!".format(tournamentTeams1[order[pos]]))
#print outs the winning team of the tournament
the exact error message:
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
main()
File "/Users/MunshiMuhammed/Desktop/Coursework Coding Folder/Actually done coursework m8 (2).py", line 47, in main
main()
File "/Users/MunshiMuhammed/Desktop/Coursework Coding Folder/Actually done coursework m8 (2).py", line 129, in main
main()
File "/Users/MunshiMuhammed/Desktop/Coursework Coding Folder/Actually done coursework m8 (2).py", line 244, in main
results()
File "/Users/MunshiMuhammed/Desktop/Coursework Coding Folder/Actually done coursework m8 (2).py", line 296, in results
print("Congratulations to team {0} for winning the tournament!".format(tournamentTeams1[order[pos]]))
IndexError: list index out of range
The text file that is being read from in the results function:
(the first line the team name, the second is the home points and the third is the away points. the next line is the next team)
3
0
0
4
3
0
These are the print statements asked for (tournamentTeams1, order and pos)
['3', '4']
[1, 0]
1
1: 4 (score 3) (away score 0)
['3', '4']
[1, 0]
1
2: 3 (score 0) (away score 0)
Congratulations to team 3 for winning the tournament!
Once again, this function only works if it is accessed after a restart of the idle.
As mentioned in the comments, that's a lot of code to wade through.
To get better responses MCVE is key. Take a look at the error message, and you see that it's occurring in the results function. So you should try to replicate the error with just that function, plus some minimal data. If you can't, you need to check what inputs are going into the function (which is what inserting the print statements were about). Then figure out what bits of your code was producing those weird inputs, and try to isolate that bit of the code. Repeat the process until you've narrowed down the area of code where the problem is likely to lie. Then post the bit of the code, along with the inputs and outputs. Welcome to the wonderful world of debugging!
All that said, I did go through the code, and I think I know what's going wrong.
When you call main() recursively, you are actually calling it without closing the tournamentName file, and then you are trying to access that same file in the results() function. Below is the problematic recursive call to main(), in the 'fixtures' part of your code.
with open(tournamentName + ".txt", mode = "w", encoding = "utf-8") as tournamentFile:
for counter in range (len(tournamentList)):
#for loop executes the following code the once for each element in array "tournamentList"
tournamentFile.write(str(tournamentList[counter]) + "\n")
#writes variable "tournamentList" to "tournamentName + ".txt"" using for loop
main() #Notice the indentation!
The indentation means the tournamentName.txt file is going to already be accessed in write mode, so you are getting an empty file when you try accessing it from the results() function. Your results() function throws an IndexError at the final line if the tournamentName.txt file is empty.
The immediate solution is to take the recursive call to main() outside of the with open(...), i.e. it should look like:
with open(tournamentName + ".txt", mode = "w", encoding = "utf-8") as tournamentFile:
#Your for loop remains here
main() #At this point tournamentName.txt is closed, available for results() to access
You need to update it in all three places of your code where this occurs.
On the other hand, as #pm-2ring states, recursive calls to main() is probably not the best idea. I would strongly recommend restructuring your code so that the main function becomes a loop that looks like below.
def main():
print("Welcome to Tournament Tracker")
while True:
response = input("would you like to begin a new tournament (new), input the results of a fixture (fixture) or view the tournament standings(standings)\n")
if response == "new":
create_new_tournament()
elif response == "fixture":
add_fixtures()
elif response == "standings":
print_results()
return
I noticed four other big issues with your code:
Your results() function has a bug where the team with the lowest score ends up at the end of the order list, while it should be the team with the highest score.
Your main() function is way way too long. Splitting it into pieces will help a lot with what I wrote at the start - small functions make it easy to isolate the part of the code that is causing problems, and make it easy to post small code snippets onto stackoverflow.
Your comments describe what the code is doing too literally, and don't give enough details on what the intended effects are. After you write short functions, you should explain what inputs those functions expect, and what output they are supposed to produce. Often, that's all the commenting you need in Python (assuming you're careful with function and variable names!)
Your code has a lot of duplication, especially in the 'fixtures' section. You need to try hard not to copy and paste code, because that makes debugging/updating much harder - you might fix one bit of the code but forget an identical section.
I am working on a program that estimates the statistic Tajima's D in a series of sliding windows across a chromosome. The chromosome itself is also divided into a number of different regions with (hopefully) functional significance. The sliding window analysis is performed by my script on each region.
At the start of the program, I define the size of the sliding windows and the size of the steps that move from one window to the next. I import a file which contains the coordinates for each different chromosomal region, and import another file which contains all the SNP data I am working with (this is read line-by-line, as it is a large file). The program loops through the list of chromosomal locations. For each location, it generates an index of steps and windows for the analysis, partitions the SNP data into output files (corresponding with the steps), calculates key statistics for each step file, and combines these statistics to estimate Tajima's D for each window.
The program works well for small files of SNP data. It also works well for the first iteration over the first chromosomal break point. However, for large files of SNP data, the step size in the analysis is inexplicably decreased as the program iterates over each chromosomal regions. For the first chromosomal regions, the step size is 2500 nucleotides (this is what it is suppose to be). For the second chromosome segment, however, the step size is 1966, and for the third it is 732.
If anyone has any suggestions at to why this might be the case, please let me know. I am especially stumped as this program seems to work size for small files but not for larger ones.
My code is below:
import sys
import math
import fileinput
import shlex
import string
windowSize = int(500)
stepSize = int(250)
n = int(50) #number of individuals in the anaysis
SNP_file = open("SNPs-1.txt",'r')
SNP_file.readline()
breakpoints = open("C:/Users/gwilymh/Desktop/Python/Breakpoint coordinates.txt", 'r')
breakpoints = list(breakpoints)
numSegments = len(breakpoints)
# Open a file to store the Tajima's D results:
outputFile = open("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/Tajima's D estimates.txt", 'a')
outputFile.write(str("segmentNumber\tchrSegmentName\tsegmentStart\tsegmentStop\twindowNumber\twindowStart\twindowStop\tWindowSize\tnSNPs\tS\tD\n"))
#Calculating parameters a1, a2, b1, b2, c1 and c2
numPairwiseComparisons=n*((n-1)/2)
b1=(n+1)/(3*(n-1))
b2=(2*(n**2+n+3))/(9*n*(n-1))
num=list(range(1,n)) # n-1 values as a list
i=0
a1=0
for i in num:
a1=a1+(1/i)
i=i+1
j=0
a2=0
for j in num:
a2=a2+(1/j**2)
j=j+1
c1=(b1/a1)-(1/a1**2)
c2=(1/(a1**2+a2))*(b2 - ((n+2)/(a1*n))+ (a2/a1**2) )
counter6=0
#For each segment, assign a number and identify the start and stop coodrinates and the segment name
for counter6 in range(counter6,numSegments):
segment = shlex.shlex(breakpoints[counter6],posix = True)
segment.whitespace += '\t'
segment.whitespace_split = True
segment = list(segment)
segmentName = segment[0]
segmentNumber = int(counter6+1)
segmentStartPos = int(segment[1])
segmentStopPos = int(segment[2])
outputFile1 = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_Count of SNPs and mismatches per step.txt")%(str(segmentNumber),str(segmentName))), 'a')
#Make output files to index the lcoations of each window within each segment
windowFileIndex = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_windowFileIndex.txt")%(str(segmentNumber),str(segmentName))), 'a')
k = segmentStartPos - 1
windowNumber = 0
while (k+1) <=segmentStopPos:
windowStart = k+1
windowNumber = windowNumber+1
windowStop = k + windowSize
if windowStop > segmentStopPos:
windowStop = segmentStopPos
windowFileIndex.write(("%s\t%s\t%s\n")%(str(windowNumber),str(windowStart),str(windowStop)))
k=k+stepSize
windowFileIndex.close()
# Make output files for each step to export the corresponding SNP data into + an index of these output files
stepFileIndex = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_stepFileIndex.txt")%(str(segmentNumber),str(segmentName))), 'a')
i = segmentStartPos-1
stepNumber = 0
while (i+1) <= segmentStopPos:
stepStart = i+1
stepNumber = stepNumber+1
stepStop = i+stepSize
if stepStop > segmentStopPos:
stepStop = segmentStopPos
stepFile = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_step_%s.txt")%(str(segmentNumber),str(segmentName),str(stepNumber))), 'a')
stepFileIndex.write(("%s\t%s\t%s\n")%(str(stepNumber),str(stepStart),str(stepStop)))
i=i+stepSize
stepFile.close()
stepFileIndex.close()
# Open the index file for each step in current chromosomal segment
stepFileIndex = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_stepFileIndex.txt")%(str(segmentNumber),str(segmentName))), 'r')
stepFileIndex = list(stepFileIndex)
numSteps = len(stepFileIndex)
while 1:
currentSNP = SNP_file.readline()
if not currentSNP: break
currentSNP = shlex.shlex(currentSNP,posix=True)
currentSNP.whitespace += '\t'
currentSNP.whitespace_split = True
currentSNP = list(currentSNP)
SNPlocation = int(currentSNP[0])
if SNPlocation > segmentStopPos:break
stepIndexBin = int(((SNPlocation-segmentStartPos-1)/stepSize)+1)
#print(SNPlocation, stepIndexBin)
writeFile = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_step_%s.txt")%(str(segmentNumber),str(segmentName),str(stepIndexBin))), 'a')
writeFile.write((("%s\n")%(str(currentSNP[:]))))
writeFile.close()
counter3=0
for counter3 in range(counter3,numSteps):
# open up each step in the list of steps across the chromosomal segment:
L=shlex.shlex(stepFileIndex[counter3],posix=True)
L.whitespace += '\t'
L.whitespace_split = True
L=list(L)
#print(L)
stepNumber = int(L[0])
stepStart = int(L[1])
stepStop = int(L[2])
stepSize = int(stepStop-(stepStart-1))
#Now open the file of SNPs corresponding with the window in question and convert it into a list:
currentStepFile = open(("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_step_%s.txt")%(str(segmentNumber),str(segmentName),str(counter3+1)),'r')
currentStepFile = list(currentStepFile)
nSNPsInCurrentStepFile = len(currentStepFile)
print("number of SNPs in this step is:", nSNPsInCurrentStepFile)
#print(currentStepFile)
if nSNPsInCurrentStepFile == 0:
mismatchesPerSiteList = [0]
else:
# For each line of the file, estimate the per site parameters relevent to Tajima's D
mismatchesPerSiteList = list()
counter4=0
for counter4 in range(counter4,nSNPsInCurrentStepFile):
CountA=0
CountG=0
CountC=0
CountT=0
x = counter4
lineOfData = currentStepFile[x]
counter5=0
for counter5 in range(0,len(lineOfData)):
if lineOfData[counter5]==("A" or "a"): CountA=CountA+1
elif lineOfData[counter5]==("G" or "g"): CountG=CountG+1
elif lineOfData[counter5]==("C" or "c"): CountC=CountC+1
elif lineOfData[counter5]==("T" or "t"): CountT=CountT+1
else: continue
AxG=CountA*CountG
AxC=CountA*CountC
AxT=CountA*CountT
GxC=CountG*CountC
GxT=CountG*CountT
CxT=CountC*CountT
NumberMismatches = AxG+AxC+AxT+GxC+GxT+CxT
mismatchesPerSiteList=mismatchesPerSiteList+[NumberMismatches]
outputFile1.write(str(("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n")%(segmentNumber, segmentName,stepNumber,stepStart,stepStop,stepSize,nSNPsInCurrentStepFile,sum(mismatchesPerSiteList))))
outputFile1.close()
windowFileIndex = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_windowFileIndex.txt")%(str(segmentNumber),str(segmentName))), 'r')
windowFileIndex = list(windowFileIndex)
numberOfWindows = len(windowFileIndex)
stepData = open((("C:/Users/gwilymh/Desktop/Python/Sliding Window Analyses-2/%s_%s_Count of SNPs and mismatches per step.txt")%(str(segmentNumber),str(segmentName))), 'r')
stepData = list(stepData)
numberOfSteps = len(stepData)
counter = 0
for counter in range(counter, numberOfWindows):
window = shlex.shlex(windowFileIndex[counter], posix = True)
window.whitespace += "\t"
window.whitespace_split = True
window = list(window)
windowNumber = int(window[0])
firstCoordinateInCurrentWindow = int(window[1])
lastCoordinateInCurrentWindow = int(window[2])
currentWindowSize = lastCoordinateInCurrentWindow - firstCoordinateInCurrentWindow +1
nSNPsInThisWindow = 0
nMismatchesInThisWindow = 0
counter2 = 0
for counter2 in range(counter2,numberOfSteps):
step = shlex.shlex(stepData[counter2], posix=True)
step.whitespace += "\t"
step.whitespace_split = True
step = list(step)
lastCoordinateInCurrentStep = int(step[4])
if lastCoordinateInCurrentStep < firstCoordinateInCurrentWindow: continue
elif lastCoordinateInCurrentStep <= lastCoordinateInCurrentWindow:
nSNPsInThisStep = int(step[6])
nMismatchesInThisStep = int(step[7])
nSNPsInThisWindow = nSNPsInThisWindow + nSNPsInThisStep
nMismatchesInThisWindow = nMismatchesInThisWindow + nMismatchesInThisStep
elif lastCoordinateInCurrentStep > lastCoordinateInCurrentWindow: break
if nSNPsInThisWindow ==0 :
S = 0
D = 0
else:
S = nSNPsInThisWindow/currentWindowSize
pi = nMismatchesInThisWindow/(currentWindowSize*numPairwiseComparisons)
print(nSNPsInThisWindow,nMismatchesInThisWindow,currentWindowSize,S,pi)
D = (pi-(S/a1))/math.sqrt(c1*S + c2*S*(S-1/currentWindowSize))
outputFile.write(str(("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n")%(segmentNumber,segmentName,segmentStartPos,segmentStopPos,windowNumber,firstCoordinateInCurrentWindow,lastCoordinateInCurrentWindow,currentWindowSize,nSNPsInThisWindow,S,D)))
A quick search shows that you do change your stepSize on line 110:
stepStart = int(L[1])
stepStop = int(L[2])
stepSize = int(stepStop-(stepStart-1))
stepStop and stepStart appear to depend on your files' contents, so we can't debug it further.