My program shown below has the goal of outputting statements based off two criteria:(Year and Location) Once that was accomplished, my next goal is to match year with Yearlink and Location with location. location and year are both input statements. The output should be a statement that outputs values from that row. For some reason, I always receive an error about too many values to unpack. Also when I fix that error, it never outputs anything for that section of the program. The first part of program is outputting correctly. Second part is either giving me Value Error or not outputting at all. My excel sheet is posted if anyone wants a better idea of what I am talking about. Anyway I tried everything but nothing was working for me.
Traceback (most recent call last):
File "C:/Users/RoszkowskiM/Desktop/win4.py", line 134, in <module>
for From,To,Max,Min in data:
ValueError: too many values to unpack
-
LOAD_GEN_DATAFILE = 'C:\Users\RoszkowskiM\Desktop\Data_2016.csv' # CSV File to Read
# read the entire CSV into Python.
# CSV has columns starting with Year,busnum,busname,scaled_power,tla,location
data = list(csv.reader(open(LOAD_GEN_DATAFILE)))
mydict = {}
for row in data:
Year,busnum,busname,scaled_power,tla,Location,Yearlink,From,To,Max,Min = row[0:12]
#If this is a year not seen before, add it to the dictionary
if Year not in mydict:
mydict[Year] = {}
busses_in_year = mydict[Year]
if Location not in busses_in_year:
busses_in_year[Location] = []
#Add the bus to the list of busses that stop at this location
busses_in_year[Location].append((busnum,busname,scaled_power))
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------
#User Input Statement
year = raw_input("Please Select Year of Study: ")
print("\n")
commands = ["Millwood-Buchanan", "Astoria-East-Corona", "Bronx", "DUNWOODIE-North-Sherman_Creek",
"Vernon", "Greenwood-StatenIsland","West_49th","East_13th","Staten_Island","East_River",
"East_View","DUNWOODIE-SOUTH","Corona-Jamaica","Astoria-East-Corona-Jamaica",
"Astoria-West-Queensbridge-Vernon","Astoria-West-Queensbridge"]
max_columns = 50
for index, commands in enumerate(commands):
stars_amount = max(max_columns - len(commands), 0)
row = "# {} {}({})".format(commands, "." * stars_amount, index + 1)
print(row)
location=raw_input(" \n The list above show the TLA Pockets as well as the ID numbers assigned to them ()\n\n Please enter the ID #: ")
print("\n")
Year=year
Location=location
if Year in mydict and Location in mydict[Year]:
busses_in_year = mydict[Year]
print("Here are all the busses at that location for that year and the new LOAD TOTAL: ")
print("\n")
#Busnum, busname,scaled_power read from excel sheet matching year and location
for busnum,busname,scaled_power in busses_in_year[Location]:
scaled_power= float(scaled_power)
busnum = int(busnum)
print('Bus #: %d\t' % busnum ,'Area Station: %s\t'% busname,'New Load Total: %d MW\t' % scaled_power)
else:
exit
-
for row in data:
Year,busnum,busname,scaled_power,tla,Location,Yearlink,From,To,Max,Min = row[0:11]
if Yearlink==year and Location==location:
for From,To,Max,Min in data:
From=int(From)
To=int(To)
Max=float(Max)
Min=float(Min)
print('From Bus #: %d\t' % From ,'To Bus #: %d\t'% To,'VMAX: %d pu\t' % Max, 'VMIN: %d pu\t' % Min)
else:
exit
You are iterating over data to get the rows, but then you iterate again over data to get From, To, Max and Min, which you had already unpacked. That line doesn't make sense. This should work:
for row in data:
data_location, year_link, from_, to, max_value, min_value = row[5:11]
output = 'From Bus #: {}\tTo Bus #: {}\tVMAX: {} pu\tVMIN: {} pu\t'
if year_link == year and data_location == location:
print(output.format(from_, to, max_value, min_value))
I simplified a bit and changed the variable names, but the only thing you have to do is remove that spurious for line.
Related
I have a file of notes that im trying to convert to a dictionary. I got the script working but failed to output the data im looking for when there are repeated values.
In short took the file commands or comments which are separated by # as per below. I take that list and seperate the 1st column "key" by # and the rest is the comment or definition. Then i check the magic word im looking for, parse it match it and then to out.
Flashcards file as per below
> car # automobile 4 wheels and run
> washington dc # the capital of United States
> fedora # an operating distro
> cat file # reads the file
> car nissan # altima
> car nissan # altima ## first car
> car nissan # maxima
> car nissan # rougue
flashcard_dict = dict()
flashcard_file = open('FlashCards','r')
enter = input("Searching nemo: ")
firstcolumn_str_list = list()
for x in flashcard_file:
flashcard_sprint = x.strip()
flascard_clean = flashcard_sprint.split("#",1)
firstcolumn_str = flascard_clean[0]
firstcolumn = firstcolumn_str.strip()
firstcolumn_str_list.append(firstcolumn)
secondcolumn = flascard_clean[1]
flashcard_dict[firstcolumn] = secondcolumn
print
print ("###" * 3)
lista = list()
# this is version 4 - where lambda works but fails as it matches the string in all words.
# so if the word is "es" all patterns are matched that has "es" AND NOT the specific word
filter_object = filter(lambda a: enter in a, firstcolumn_str_list)
for x in filter_object:
lista.append(x)
print (lista)
cc = 0
if cc < len(lista):
for lambdatodictmatch in lista:
if lambdatodictmatch in flashcard_dict:
print (flashcard_dict[lambdatodictmatch])
else:
print ("NONEsense... nothing here")
else:
print ("NONEsense... nothing here")
Again it works but when i search for car nissan. I get four responses but i only get the last "rougue" output or i get 4 repeated response "rougue".
what's the best way to accomplish this?
If you may have repeated elements then you should always use lists to keep even single value
if firstcolumn not in flashcard_dict:
flashcard_dict[firstcolumn] = []
firstcolumn[firstcolumn].append(secondcolumn)
instead of
flashcard_dict[firstcolumn] = secondcolumn
EDIT:
Full working code with other changes
first I used shorter and more readable names for variables,
I read file at start and later use loop to ask for different cards.
I added command !keys to display all keys, and !exit to exit loop and finish program,
list(sorted(flashcards.keys())) gives all keys from dictionary without repeating values (and sorted)
I used io only to simulate file in memory - so everyone can simply copy and run this code (without creating file FlashCards) but you should use open(...)
text = '''car # automobile 4 wheels and run
washington dc # the capital of United States
fedora # an operating distro
cat file # reads the file
car nissan # altima
car nissan # altima ## first car
car nissan # maxima
car nissan # rougue
'''
import io
# --- constansts ---
DEBUG = True
# --- functions ---
def read_data(filename='FlashCards'):
if DEBUG:
print('[DEBUG] reading file')
flashcards = dict() # with `s` at the end because it keeps many flashcards
#file_handler = open(filename)
file_handler = io.StringIO(text)
for line in file_handler:
line = line.strip()
parts = line.split("#", 1)
key = parts[0].strip()
value = parts[1].strip()
if key not in flashcards:
flashcards[key] = []
flashcards[key].append(value)
all_keys = list(sorted(flashcards.keys()))
return flashcards, all_keys
# --- main ---
# - before loop -
# because words `key` and `keys` are very similar and it is easy to make mistake in code - so I added prefix `all_`
flashcards, all_keys = read_data()
print("#########")
# - loop -
while True:
print() # empty line to make output more readable
enter = input("Searching nemo (or command: !keys, !exit): ").strip().lower()
print() # empty line to make output more readable
if enter == '!exit':
break
elif enter == '!keys':
#print( "\n".join(all_keys) )
for key in all_keys:
print('key>', key)
elif enter.startswith('!'):
print('unknown command:', enter)
else:
# keys which have `enter` only at
#selected_keys = list(filter(lambda text: text.startswith(enter), all_keys))
# keys which have `enter` in any place (at the beginning, in the middle, at the end)
selected_keys = list(filter(lambda text: enter in text, all_keys))
print('selected_keys:', selected_keys)
if selected_keys: # instead of `0 < len(selected_keys)`
for key in selected_keys:
# `selected_keys` has to exist in `flashcards` so there is no need to check if `key` exists in `flashcards`
print(key, '=>', flashcards[key])
else:
print("NONEsense... nothing here")
# - after loop -
print('bye')
I just started studying Python and I have homework that I don't know how to begin with.
I have to read info about the employees of a company: name, age, occupation, salary, years_in_the company from a (txt) file. They are found on separate lines, and are split by a tab, for example:
Helen 20 Network Designer 5449 9
Jasmine 40 Software Architect 2536 1
Phoebe 28 Software Engineer 2627 7
Aysha 34 Software Developer 6441 3
Now, with this info I have to create a few functions like the average age of the employees, best-paid job, best-paid employee and so on. I do not know how to properly read the data from the file and how to implement the functions. I was thinking to define the functions at first, and then read all the data from the file, but a friend of mine told me that I could define each function and inside it I could read the necessary data.
For example, if I were to calculate the average age of the employees, I was thinking about doing it like this:
def avg(*args):
count = len(args)
if args > 0:
age_sum = 0
for i in args:
age_sum += i
return age_sum / count
else:
return 0
The problem is, I don't know how to fetch the proper data to the function. Can anyone please help me understand how to do it properly?
This is the one way, but there might best way than this to do that, but at least this will help you to deal with your problem. You can optimize the code plus you can change the variable from int to float for better coverage of avg etc and there should not be an empty line between lines in the file.
#print all detail
def print_all():
file = open("data.txt","r")
for line in file:
fields = line.split(" ")
print ("name "+ fields[0])
print ("age "+ fields[1])
print ("occupation "+ fields[2])
print ("type occupation "+ fields[3])
print ("salary "+ fields[4])
print ("years_in_the_company "+ fields[5])
file.close()
# avg salary
def avg__salary(employ = "salary" ):
file = open("data.txt","r")
avg=0
for salary in file:
salary_field = salary.split(" ")
avg=avg+int(salary_field[4])
file.close()
return avg
# avg age
def avg__age(employ = "age" ):
file = open("data.txt","r")
avg_age=0
for age in file:
age_field = age.split(" ")
avg_age=avg_age+int(age_field[1])
file.close()
return avg_age
# best paid job
def best_paid(employ = "paid" ):
file = open("data.txt","r")
bestpaid=0
for age in file:
age_field = age.split(" ")
if bestpaid < age_field[4]:
bestpaid=age_field[4]
file.close()
return bestpaid
number_of_lines=open('data.txt', 'r').read().count("\n")
print("All employ detail")
print_all()
print("Avg salary is",avg__salary()/number_of_lines)
print("Avg age is",avg__age()/number_of_lines)
print("Best paid is",best_paid())
So if I have the following code:
database = []
Name = input("What's the members name?")
MT = input("What membership type?")
DOB = input("What is the member DOB?")
DJ = (now.day ,"/" , now.month, "/", now.year)
year1 = int(now.year)
month1 = int(now.month)
day1 = int(now.day)
ry = int(year1 + 1)
rm = month1
rd = day1
renewal = (day1, month1, year1 + 1)
details = ["Name:", Name, "Membership Type:", MT, "Date of Birth:", DOB, "Date Joined:", DJ,"Renewal Date:", renewal, "Renewal Year:", ry]
database.append(details)
menu()
How would I go about saving (database) to a text file / csv file to be read later.
I have tried pickle but the issue is I need to be able to get each part of the array seperate.
For example if I type:
print(database[1])
I will return all Names stored as "Name", however if I were to write the file using pickle when I bring it back in then
print (database[1])
now shows the entirety of the second user added. I need to be able to save (database) and have it in the same format when read back in.
Expected output using JSON or Pickle(assuming the first user inputted name as "Jeff" and second inputted name as "John")
print (database[1])
Jeff
John
Actual output:
["Name:", John, "Membership Type:", MT, "Date of Birth:", DOB, "Date Joined:", DJ,"Renewal Date:", renewal, "Renewal Year:", ry]
Sorry for the bad explanation I'm new to python.
It seems you are creating an array of records. Try accessing the data in this way:
print(database[0][1]) #[0] for the first record, [1] for second item
print(database[1][1]) #second user, second item
I'm getting raw data then reordering the columns, adding data based on data from multiple files, adding some hardcoded data, then saving to an "output.csv" file.
For example...
File1.csv: (Retrieved Data)
person, date_time, site, status
Person1,01/13/16 10:38,SiteA,I
Person1,01/20/16 12:53,SiteC,O
Person2,01/21/16 14:45,SiteB,O
Person3,01/17/16 12:17,SiteA,I
Person3,01/25/16 10:15,SiteB,L
File2.csv: (Fixed Data_1)
site,code
SiteA,101
SiteB,102
SiteC,103
File3.csv: (Fixed Data_2)
period_start_time,period_end_time,period
00:00,07:59,0
08:00,09:00,1
09:01,10:00,2
10:01,11:00,3
11:01,12:00,4
12:01,13:00,5
13:01,14:00,6
14:01,15:00,7
15:01,23:59,X
File1 has raw data.
The last column has a "I", "O" and a "L".
The "I" stands for IN.
The "O" stands for OUT.
The "L" stands for LATE.
This example has three students that have gone in or out of sites A, B or C.
Note, if they are "L" or LATE they are still going IN.
File2 has "site codes".
File3 has a first column stating the period_start_time and the second is the period_end_time.
The third column is the period.
I need to create a output.csv file:
WHERE,WHOM,PERIOD,DATE,TIME_IN,TIME_OUT,USERNAME
WHERE = needs to be the corresponding site code from File2.
WHOM = is the person.
PERIOD = if the time is 10:38, then the period is "3", given by File3.
DATE = show time as 'mm/dd/yy'.
TIME_IN = show time as 'HH:MM' if the status is "I" or "L", leave blank if it doesn't.
TIME_OUT = show time as 'HH:MM' if the status is "O", leave blank if it doesn't.
USERNAME = is hardcoded "Username".
The output.csv file should read like this, given the example data above.
output.csv: (Reformatted Data)
101,Person1,3,01/13/16,10:38,,Username
103,Person1,5,01/20/16,,12:53,Username
102,Person2,7,01/21/16,,14:45,Username
101,Person3,5,01/17/16,12:17,,Username
102,Person3,3,01/25/16,10:15,,Username
Note the corresponding code in the first column.
Also note the PERIOD, and the blanks for TIME_IN and TIME_OUT columns.
Finally got it.
from datetime import datetime as dt
import csv
class TimePeriod:
def __init__(self, starttime, endtime, periodname):
self.starttime = starttime
self.endtime = endtime
self.periodname = periodname
def get_time_list(time_file):
timelist = list()
with open(time_file) as inputs:
for line in inputs:
starttime, endtime, periodname = line.strip().split(",")
timelist.append(TimePeriod(starttime, endtime, periodname))
return timelist
def get_site_code_dict(site_code_file):
mydict = dict()
with open(site_code_file) as inputs:
for line in inputs:
site,code = line.strip().split(",")
mydict[site] = code
return mydict
def process_raw(raw_file, site_code_dict):
with open(raw_file) as inputs, open('ouput.csv', 'w') as outlist:
for line in inputs:
person, date_time, site, status = line.strip().split(",")
time_object = dt.strptime(date_time, '%m/%d/%y %H:%M')
date = time_object.strftime('%m/%d/%y')
time = time_object.strftime('%H:%M')
filteredlist = filter(lambda x: time >= x.starttime and time <= x.endtime, time_list)
outlist.write(site_code_dict[site]+',')
outlist.write(person+',')
outlist.write(date+',')
outlist.write(filteredlist[0].periodname+',')
if status == "I" or status == "L":
outlist.write(time+',')
else:
outlist.write(""+',')
if status == "O":
outlist.write(time+',')
else:
outlist.write(""+',')
outlist.write("Username"+'\n')
outlist.close()
if __name__ == "__main__":
site_code_dict = get_site_code_dict("file2.csv")
time_list = get_time_list("file3.csv")
process_raw("file1.csv", site_code_dict)
Output data from the csv file:
101,Person1,01/13/16,3,10:38,,Username
103,Person1,01/20/16,5,,12:53,Username
102,Person2,01/21/16,7,,14:45,Username
101,Person3,01/17/16,5,12:17,,Username
102,Person3,01/25/16,3,10:15,,Username
With the above code, I've got the columns in order.
The 1st column has the correct code.
The DATE column has the just the date in 'mm/dd/yy' format.
The TIME_IN column has only military time, if the record is "I" or "L".
And the TIME_OUT column has military time time, if it is "O".
I have the period done, by using a "class" TimePeriod.
Thanks for the help, as I am very much a novice.
def get_site_code_dict(site_code_file):
mydict = dict()
with open(site_code_file) as inputs:
for line in inputs:
site,code = line.strip().split(",")
mydict[site] = code
return mydict
def process_raw(raw_file, site_code_dict):
with open(raw_file) as inputs:
for line in inputs:
person, date_time, site, status = line.strip().split(",")
outlist = list()
outlist.append(site_code_dict[site])
outlist.append(person)
outlist.append(date_time)
outlist.append(status)
print ",".join(outlist)
if __name__ == "__main__":
site_code_dict = get_site_code_dict("file2")
process_raw("file1", site_code_dict)
Output:
101,Person1,01/13/16 10:38,I
103,Person1,01/20/16 12:53,O
102,Person2,01/21/16 14:45,O
You can create key-value pair as get_site_code_dict to bind the site name and code number, and then use it to process your raw data.
I'm getting a keyerror exception when I input a player name here that is not in the records list. I can search it and get back any valid name, but if I input anything else, i get a keyerror. I'm not really sure how to go about handling this since it's kindof confusing already dealing with like 3 sets of data created from parsing my file.
I know this code is bad I'm new to python so please excuse the mess - also note that this is a sortof test file to get this functionality working, which I will then write into functions in my real main file. Kindof a testbed here, if that makes any sense.
This is what my data file, stats4.txt, has in it:
[00000] Cho'Gath - 12/16/3 - Loss - 2012-11-22
[00001] Fizz - 12/5/16 - Win - 2012-11-22
[00002] Caitlyn - 13/4/6 - Win - 2012-11-22
[00003] Sona - 4/5/9 - Loss - 2012-11-23
[00004] Sona - 2/1/20 - Win - 2012-11-23
[00005] Sona - 6/3/17 - Loss - 2012-11-23
[00006] Caitlyn - 14/2/16 - Win - 2012-11-24
[00007] Lux - 10/2/14 - Win - 2012-11-24
[00008] Sona - 8/1/22 - Win - 2012-11-27
Here's my code:
import re
info = {}
records = []
search = []
with open('stats4.txt') as data:
for line in data:
gameid = [item.strip('[') for item in line.split(']')]
del gameid[-1]
gameidstr = ''.join(gameid)
gameid = gameidstr
line = line[7:]
player, stats, outcome, date = [item.strip() for item in line.split('-', 3)]
stats = dict(zip(('kills', 'deaths', 'assists'), map(int, stats.split('/'))))
date = tuple(map(int, date.split('-')))
info[player] = dict(zip(('gameid', 'player', 'stats', 'outcome', 'date'), (gameid, player, stats, outcome, date)))
records.append(tuple((gameid, info[player])))
print "\n\n", info, "\n\n" #print the info dictionary just to see
champ = raw_input() #get champion name
#print info[champ].get('stats').get('kills'), "\n\n"
#print "[%s] %s - %s/%s/%s - %s-%s-%s" % (info[champ].get('gameid'), champ, info[champ].get('stats').get('kills'), info[champ].get('stats').get('deaths'), info[champ].get('stats').get('assists'), info[champ].get('date')[0], info[champ].get('date')[1], info[champ].get('date')[2])
#print "\n\n"
#print info[champ].values()
i = 0
for item in records: #this prints out all records
print "\n", "[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (records[i][0], records[i][1]['player'], records[i][1]['stats']['kills'], records[i][1]['stats']['deaths'], records[i][1]['stats']['assists'], records[i][1]['outcome'], records[i][1]['date'][0], records[i][1]['date'][1], records[i][1]['date'][2])
i = i + 1
print "\n" + "*" * 50
i = 0
for item in records:
if champ in records[i][1]['player']:
search.append(records[i][1])
else:
pass
i = i + 1
s = 0
if not search:
print "no availble records" #how can I get this to print even if nothing is inputted in raw_input above for champ?
print "****"
for item in search:
print "\n[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (search[s]['gameid'], search[s]['player'], search[s]['stats']['kills'], search[s]['stats']['deaths'], search[s]['stats']['assists'], search[s]['outcome'], search[s]['date'][0], search[s]['date'][1], search[s]['date'][2])
s = s + 1
I tried setting up a Try; Except sort of thing but I couldn't get any different result when entering an invalid player name. I think I could probably set something up with a function and returning different things if the name is present or not but I think I've just gotten myself a bit confused. Also notice that no match does indeed print for the 8 records that aren't matches, though thats not quite how I want it to work. Basically I need to get something like that for any invalid input name, not just a valid input that happens to not be in a record in the loop.
Valid input names for this data are:
Cho'Gath, Fizz, Caitlyn, Sona, or Lux - anything else gives a keyerror, thats what I need to handle so it doesn't raise an error and instead just prints something like "no records available for that champion" (and prints that only once, rather then 8 times)
Thanks for any help!
[edit] I was finally able to update this code in the post (thank you martineau for getting it added in, for some reason backticks aren't working to block code and it was showing up as bold normal text when i pasted. Anyways, look at if not search, how can I get that to print even if nothing is entered at all? just pressing return on raw_input, currently it prints all records after **** even though i didn't give it any search champ
where is your exact error occurring?
i'm just assuming it is when champ = raw_input() #get champion name
and then info[champ]
you can either check if the key exists first
if champ not in info:
print 'no records avaialble'
or use get
if info.get(champ)
or you can just try and access the key
try:
info[champ]
# do stuff
except KeyError:
print 'no records available'
the more specific you can be in your question the better, although you explained your problem you really didn't include any specifics Please always include a traceback if available, and post the relevant code IN your post not on a link.
Here's some modifications that I think address your problem. I also reformatted the code to make it a little more readable. In Python it's possible to continue long lines onto the next either by ending with a \ or just going to the next line if there's an unpaired '(' or '[' on the previous line.
Also, the way I put code in my questions or answer here is by cutting it out of my text editor and then pasting it into the edit window, after that I make sure it's all selected and then just use the {} tool at the top of edit window to format it all.
import re
from pprint import pprint
info = {}
records = []
with open('stats4.txt') as data:
for line in data:
gameid = [item.strip('[') for item in line.split(']')]
del gameid[-1]
gameidstr = ''.join(gameid)
gameid = gameidstr
line = line[7:]
player, stats, outcome, date = [item.strip() for item in line.split('-', 3)]
stats = dict(zip(('kills', 'deaths', 'assists'), map(int, stats.split('/'))))
date = tuple(map(int, date.split('-')))
info[player] = dict(zip(('gameid', 'player', 'stats', 'outcome', 'date'),
(gameid, player, stats, outcome, date)))
records.append(tuple((gameid, info[player])))
#print "\n\n", info, "\n\n" #print the info dictionary just to see
pprint(info)
champ = raw_input("Champ's name: ") #get champion name
#print info[champ].get('stats').get('kills'), "\n\n"
#print "[%s] %s - %s/%s/%s - %s-%s-%s" % (
# info[champ].get('gameid'), champ, info[champ].get('stats').get('kills'),
# info[champ].get('stats').get('deaths'), info[champ].get('stats').get('assists'),
# info[champ].get('date')[0], info[champ].get('date')[1],
# info[champ].get('date')[2])
#print "\n\n"
#print info[champ].values()
i = 0
for item in records: #this prints out all records
print "\n", "[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (
records[i][0], records[i][1]['player'], records[i][1]['stats']['kills'],
records[i][1]['stats']['deaths'], records[i][1]['stats']['assists'],
records[i][1]['outcome'], records[i][1]['date'][0],
records[i][1]['date'][1], records[i][1]['date'][2])
i = i + 1
print "\n" + "*" * 50
i = 0
search = []
for item in records:
if champ in records[i][1]['player']:
search.append(records[i][1])
i = i + 1
if not search:
print "no match"
exit()
s = 0
for item in search:
print "\n[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (search[s]['gameid'],
search[s]['player'], search[s]['stats']['kills'],
search[s]['stats']['deaths'], search[s]['stats']['assists'],
search[s]['outcome'], search[s]['date'][0], search[s]['date'][1],
search[s]['date'][2])
s = s + 1