how to export selected dictionary data into a file in python? - python

Right now when I check this function, in export_incomes
if income_types in expenses:
TypeError: unhashable type: 'list'
I am not sure what I did wrong here.
I did create an incomes dictionary with income_types as key and income_value as value.
Iterates over the given incomes dictionary, filters based on the given income types (a list of strings), and exports to a file.
Exports the given income types from the given incomes dictionary to the given file.
def export_incomes(incomes, income_types, file):
final_list = []
for u, p in expenses.items():
if expense_types in expenses:
final_list.append(':'.join([u,p]) + '\n')
fout = open(file, 'w')
fout.writelines(final_list)
fout.close()
If this is the income list that should be in txt if a user inputs stock, estate, work and investment, each should item and value should be on a separate line:
stock: 10000
estate: 2000
work: 80000
investment: 30000

First, you start your question with expenses but ends with incomes and the code also has incomes in the parameters so I'll go with the income.
Second, the error says the answer. "expense_types(income_types)" is a list and "expenses(incomes)" is a dictionary. You're trying to find a list (not hashable) in a dictionary.
So to make your code work:
def export_incomes(incomes, income_types, file):
items_to_export = []
for u, p in incomes.items():
if u in income_types:
items_to_export.append(': '.join([u,p]) + '\n') # whitespace after ':' for spacing
with open(file, 'w') as f:
f.writelines(items_to_export)
If I made any wrong assumption or got your intention wrong, pls let me know.

Related

Need help iterating over python dictionary values

I'm working on a program to search through a dictionaries value set and perform a method on values that match a user input. I have to compare and sort these values.
This is the code I'm working with right now
Code for value search and compare (very rough)
import nation
import pickle
KK = 1000000
pickle_in = open("nationsDict.dat","rb")
d = pickle.load(pickle_in)
k = raw_input("Enter a continent: ")
for value in d.values():
if k in d.values()[0]:
print d.values()[0]
Code for Nation class
class Nations:
KK = 1000000
def __init__(self, ctry, cont, pop, area):
self.country = ctry
self.continent = cont
self.population = float(pop)
self.area = float(area)
def popDensity(self):
popDensity = (self.population*self.KK) / self.area
popDensity = str(round(popDensity, 2))
return popDensity
Code for creating pickle dictionary
import nation
import pickle
i=0
dictUN = {}
with open('UN.txt') as f:
for line in f:
"""Data get from file"""
elements = line.strip().split(",")
n = nation.Nations(elements[0],elements[1],elements[2],elements[3])
"""Density"""
n.popDensity()
print "The density of", n.country, "is",n.popDensity(),"people per square mile."
"""Dictionary creation"""
dictVal = (n.continent, n.population, n.area)
dictUN.update({n.country: dictVal})
pickle_out = open("nationsDict.dat", "wb")
pickle.dump(dictUN, pickle_out)
pickle_out.close()
Here's a snippet from UN.txt
Mauritania,Africa,3.5,397954
Mauritius,Africa,1.3,787
Mexico,North America,120.3,761606
Micronesia,Australia/Oceania,.11,271
Monaco,Europe,.031,0.76
Mongolia,Asia,3.0,603909
Montenegro,Europe,.65,5019
Morocco,Africa,33.0,172414
My problems at this point are pretty contained to the value search and compare. Specifically, my program has to
Allow the user to search a continent (first element in value list)
Perform the method, Nations.popDensity (contained in nation class) on all matching countries
Compare the nations and return the top 5 density values per continent
I would say my one big question is how to handle the search of a dictionary by an element in a value. I've also considered about making a temp dictionary with the continent element as the key, but I'm not sure that would make my life any easier as I have to perform the popDensity method on it.
Any help is appreciated, Thanks!
Initialize pandas series object
Iterate through the dictionary.
If the continent matches:
a. calculate the population density.
b. if the value is larger than the smallest value in the pandas series:
i. remove the last entry
ii.append the value into the pandas series values and the country to the index
iii. sort the pandas series object ascending = False
If you're going to do this repeatedly, then creating a continent->country dictionary definitely will save time.
Glad it was helpful. I'll add it as an answer, so you can accept it, if you like.
Just as there is list comprehension, there is dictionary comprehension... It's pretty cool stuff! d2 = {k:d[k] for k in d.keys() if <some_elem> in d[k]} would give you a dict with a subset of the original dict that satisfies your requirements. You would have to fill in the <some_elem> in d[k] portion, because I haven't gone through all your code. You said that this is the main Q you have. Hopefully this gives you enough to solve it.

Dictionary won't store the value after restart

Here is my code. This code is for managing fruit stocks in the shop. So you type in the name of the fruit, and the amount of it. If the fruit is not registered in the dictionary, it would add the fruit and it's value to the dictionary. If the fruit is registered, it would check if its value is bigger than the original value in the dictionary. If it's bigger, it will replace the amount, but if the typed amount is smaller than the original amount, it wouldn't do anything.
I used the code below for checking for the average of the fruits. So it counts how many fruits I have bought and it accumulates it. So that later on, I can use it to find out the average by dividing the number by how many times I have accumulated it.
items[fruit_t]["av"]+=(fruit_n)
Here is question. When ever i try to add things to dictionary, it prints for first time, but when I move on to add another fruit, previously added fruit disappears. I don't get what is wrong. Also, I want to use .append instead of += as shown above, but when ever I try to do that, there's an error. I want to use append because later on, I can use len() to count how many numbers are in av
, sum up the av and divide by the len() value of av.
import pickle
def fruit():
with open('fruits.pickle', 'a') as f:
try:
items = pickle.load(f)
except ValueError:
items = {"Apple":{"av":10,"count":10},"Banana":{"av":14,"count":14},"Orange":{"av":23,"count":23},"Watermelon":{"av":54,"count":54}}
fruit_t = input("Please type in the name of the fruit: ")
fruit_n = int(input("Please type in the amount of the fruit: "))
if fruit_t in items:
items[fruit_t]["av"]+=(fruit_n)
if items[fruit_t]["count"] < fruit_n:
items[fruit_t]["count"] = fruit_n
else:
items[fruit_t] = {"av":fruit_n,"count":fruit_n}
with open('fruits.pickle', 'wb') as f:
pickle.dump(items, f)
for k in items:
print("{} monthly {}".format(k,items[k]["av"]))
print("{} total {}".format(k,items[k]["count"]))
fruit()
fruit()
Edited and working code.
import pickle
def fruit():
with open('fruits.pickle', 'rb') as f:
try:
items = pickle.load(f)
except ValueError:
items = {}
fruit_t = input("Please type in the name of the fruit: ")
fruit_n = int(input("Please type in the amount of the fruit: "))
if fruit_t in items:
items[fruit_t]["total"]+=(fruit_n)
if items[fruit_t]["count"] < fruit_n:
items[fruit_t]["count"] = fruit_n
else:
items[fruit_t] = {"total":fruit_n,"count":fruit_n}
with open('fruits.pickle', 'wb') as f:
pickle.dump(items, f)
for k in items:
print("{} monthly {}".format(k,items[k]["total"]))
print(items[k]["count"])
fruit()
fruit()
I'll answer your question with a very different approach:
pickle will not load your pickled file because you are opening the file in 'appending'-mode in line 3.
You are not noticing the error as you have enclosed the loading in a try-statement. Instead, the exception is caught and your items are loaded from default.
Solution: Change mode in open in line 3 to rb.
Given that you are not correcting the code in the question, here is what is wrong:
You have specified 'appending' as the mode in open on line 3.
This is not useful when you intend to read the file; instead use
r for reading, perhaps rb for reading a binary file.
Dedent line 8 (fruit_t = ...) as this marks the exit from the context manager starting on line 3 (with ... is a context manager). This will close the file again, as you are done reading it. Dedent following lines.
You do not need to keep track of each "purchase"; you can instead rely on 1) the sum of purchases and 2) the count of purchases. Calculating the average is very easy then. You can therefore split your dictionary into two.
On line 12, your logic eludes me and it contradicts what you write in your question.
Code example 1
from collections import Counter
fruits = {'apple':0, 'banana':0}
purchases = Counter(fruits)
fruits = Counter(fruits)
## on purchase
fr = 'apple'
buy = 4
fruits[fr] += 4
purchases[fr] += 1
See what happens if you buy a fruit that is not yet present in the Counters (i.e. set fr = 'mandarin').

Update: Python average income reading and writing files

I was writing a code to find the average household income, and how many families are below poverty line.
this is my code so far
def povertyLevel():
inFile = open('program10.txt', 'r')
outFile = open('program10-out.txt', 'w')
outFile.write(str("%12s %12s %15s\n" % ("Account #", "Income", "Members")))
lineRead = inFile.readline() # Read first record
while lineRead != '': # While there are more records
words = lineRead.split() # Split the records into substrings
acctNum = int(words[0]) # Convert first substring to integer
annualIncome = float(words[1]) # Convert second substring to float
members = int(words[2]) # Convert third substring to integer
outFile.write(str("%10d %15.2f %10d\n" % (acctNum, annualIncome, members)))
lineRead = inFile.readline() # Read next record
# Close the file.
inFile.close() # Close file
Call the main function.
povertyLevel()
I am trying to find the average of annualIncome and what i tried to do was
avgIncome = (sum(annualIncome)/len(annualIncome))
outFile.write(avgIncome)
i did this inside the while lineRead. however it gave me an error saying
avgIncome = (sum(annualIncome)/len(annualIncome))
TypeError: 'float' object is not iterable
currently i am trying to find which household that exceeds the average income.
avgIncome expects a sequence (such as a list) (Thanks for the correction, Magenta Nova.), but its argument annualIncome is a float:
annualIncome = float(words[1])
It seems to me you want to build up a list:
allIncomes = []
while lineRead != '':
...
allIncomes.append(annualIncome)
averageInc = avgIncome(allIncomes)
(Note that I have one less indentation level for the avgIncome call.)
Also, once you get this working, I highly recommend a trip over to https://codereview.stackexchange.com/. You could get a lot of feedback on ways to improve this.
Edit:
In light of your edits, my advice still stands. You need to first compute the average before you can do comparisons. Once you have the average, you will need to loop over the data again to compare each income. Note: I advise saving the data somehow for the second loop, instead of reparsing the file. (You may even wish to separate reading the data from computing the average entirely.) That might best be accomplished with a new object or a namedtuple or a dict.
sum() and len() both take as their arguments an iterable. read the python documentation for more on iterables. you are passing a float into them as an argument. what would it mean to get the sum, or the length, of a floating point number? even thinking outside the world of coding, it's hard to make sense of that.
it seems like you need to review the basics of python types.

merge values of same key in a list of dictionaries , and compare to another list of dictionaries in python3

Update: Apparently, I noticed that in my main code, when I extract the values from the list of dictionaries that I get from readExpenses.py, I store it as a set, not as a list of dictionaries.
Now, I know that I store each dictionary in the 'exp' list with these lines of code:
for e in expenses:
exp.append(e)
However, I only want the Keys Amount, and Type from those dictionaries, and not the other entries.
For reference, here is the list of keys in an expense dictionary:
"Date","Description","Type","Check Number","Amount","Balance"
As mentioned before, I only need Type and Amount.
I am trying to make a budget program, So I have this list of dictionaries:
[{'Bills': 30.0}, {'Bills': 101.53}, {'Bills': 60.0}, {'Bills': 52.45}, {'Gas': 51.17}, {500.0: 'Mortgage'}, {'Food': 5.1}]
And I'm trying to compare it to this list of dictionaries:
[{400.0: 'Bills'}, {'Gas': 100.0}, {500.0: 'Mortgage'}, {'Food': 45.0}]
The first list is how much money I spent on different services in a given month, and what category it was in, and the second dictionary is the max amount that the budget allows me to spend on said category.
The goal is, in the first dictionary, to combine all the values of the same key into one key:value pair, then compare it to the second dictionary.
So I should get this list of dictionaries out of the first one:
[{'Bills': 295.15), {'Gas': 51.17}, {500.0: 'Mortgage'}, {'Food': 5.1}]
I tried looking at this example and this one, but they are just about merging the dictionaries lists together, and not summing the values of the same key. I did try the code in the latter, but it only joined the dictionaries together. I noticed that sum only seems to work with "raw" dictionaries, and not with lists of dictionaries.
I did try this as a thought experiment:
print(sum(item['amount'] for item in exp))
I know that would sum up all the numbers under amount, rather than return a number for each category, but I wanted to try out it for the heck of it, to see if it would lead to a solution, but I got this error in return:
TypeError: 'set' object is not subscriptable
The Counter function seemed to show promise as a solution as well when I was messing around, however, it seems to only work with dictionaries that are on their own, and not with list of dictionaries.
#where exp is the first dictionary that I mentioned
a = Counter(exp)
b = Counter(exp)
c = a + b #I'm aware the math would have be faulty on this, but this was a test run
print (c)
This attempt returned this error:
TypeError: unhashable type: 'set'
Also, is there a way to do it without importing the collections module and using what comes with python as well?
My code:
from readExpense import *
from budget import *
from collections import *
#Returns the expenses by expenses type
def expensesByType(expenses, budget):
exp = []
expByType = []
bud = []
for e in expenses:
entry = {e['exptype'], e['amount']}
exp.append(entry)
for b in budget:
entry = {b['exptype'], b['maxamnt']}
bud.append(entry)
return expByType;
def Main():
budget = readBudget("budget.txt")
#printBudget(budget)
expenses = readExpenses("expenses.txt")
#printExpenses(expenses)
expByType = expensesByType(expenses, budget)
if __name__ == '__main__':
Main()
And for reference, the code from budget and readexpense respectively.
budget.py
def readBudget(budgetFile):
# Read the file into list lines
f = open(budgetFile)
lines = f.readlines()
f.close()
budget = []
# Parse the lines
for i in range(len(lines)):
list = lines[i].split(",")
exptype = list[0].strip('" \n')
if exptype == "Type":
continue
maxamount = list[1].strip('$" \n\r')
entry = {'exptype':exptype, 'maxamnt':float(maxamount)}
budget.append(entry)
return budget
def printBudget(budget):
print()
print("================= BUDGET ==================")
print("Type".ljust(12), "Max Amount".ljust(12))
total = 0
for b in budget:
print(b['exptype'].ljust(12), str("$%0.2f" %b['maxamnt']).ljust(50))
total = total + b['maxamnt']
print("Total: ", "$%0.2f" % total)
def Main():
budget = readBudget("budget.txt")
printBudget(budget)
if __name__ == '__main__':
Main()
readExpense.py
def readExpenses(file):
#read file into list of lines
#split lines into fields
# for each list create a dictionary
# add dictionary to expense list
#return expenses in a list of dictionary with fields
# date desc, exptype checknm, amnt
f = open(file)
lines=f.readlines()
f.close()
expenses = []
for i in range(len(lines)):
list = lines[i].split(",")
date = list[0].strip('" \n')
if date == "Date":
continue
description = list[1].strip('" \n\r')
exptype= list[2].strip('" \n\r')
checkNum = list[3].strip('" \n\r')
amount = list[4].strip('($)" \n\r')
balance = list[5].strip('" \n\r')
entry ={'date':date, 'description': description, 'exptype':exptype, 'checkNum':checkNum, 'amount':float(amount), 'balance': balance}
expenses.append(entry)
return expenses
def printExpenses(expenses):
#print expenses
print()
print("================= Expenses ==================")
print("Date".ljust(12), "Description".ljust(12), "Type".ljust(12),"Check Number".ljust(12), "Amount".ljust(12), "Balance".ljust(12))
total = 0
for e in expenses:
print(str(e['date']).ljust(12), str(e['description']).ljust(12), str(e['exptype']).ljust(12), str(e['checkNum']).ljust(12), str(e['amount']).ljust(12))
total = total + e['amount']
print()
print("Total: ", "$%0.2f" % total)
def Main():
expenses = readExpenses("expenses.txt")
printExpenses(expenses)
if __name__ == '__main__':
Main()
Is there a reason you're avoiding creating some objects to manage this? If it were me, I'd go objects and do something like the following (this is completely untested, there may be typos):
#!/usr/bin/env python3
from datetime import datetime # why python guys, do you make me write code like this??
from operator import itemgetter
class BudgetCategory(object):
def __init__(self, name, allowance):
super().__init__()
self.name = name # string naming this category, e.g. 'Food'
self.allowance = allowance # e.g. 400.00 this month for Food
self.expenditures = [] # initially empty list of expenditures you've made
def spend(self, amount, when=None, description=None):
''' Use this to add expenditures to your budget category'''
timeOfExpenditure = datetime.utcnow() if when is None else when #optional argument for time of expenditure
record = (amount, timeOfExpenditure, '' if description is None else description) # a named tuple would be better here...
self.expenditures.append(record) # add to list of expenditures
self.expenditures.sort(key=itemgetter(1)) # keep them sorted by date for the fun of it
# Very tempting to the turn both of the following into #property decorated functions, but let's swallow only so much today, huh?
def totalSpent(self):
return sum(t[0] for t in self.expenditures)
def balance(self):
return self.allowance - self.totalSpent()
Now I can right code that looks like:
budget = BudgetCategory(name='Food', allowance=200)
budget.spend(5)
budget.spend(8)
print('total spent:', budget.totalSpent())
print('left to go:', budget.balance())
This is just a starting point. Now you can you add methods that group (and sum) the expenditures list by decoration (e.g. "I spent HOW MUCH on Twinkies last month???"). You can add a method that parses entries from a file, or emits them to a csv list. You can do some charting based on time.

'Splitting' List into several Arrays

I'm trying to complete a Project that will show total annual sales from an specific list contained in a .txt file.
The list is formatted this way:
-lastname, firstname (string)
-45.7 (float)
-456.4 (float)
-345.5 (float)
-lastname2, firstname2 (string)
-3354.7 (float)
-54.6 (float)
-56.2 (float)
-lastname3, firstname3 (string)
-76.6 (float)
-34.2 (float)
-48.2 (float)
And so on.... Actually, 7 different "employees" followed by 12 set of "numbers" (months of the year)....but that example should suffice to give an idea of what I'm trying to do.
I need to output this specific information of every "employee"
-Name of employee
-Total Sum (sum of the 12 numbers in the list)
So my logic is taking me to this conclusion, but I don't know where to start:
Create 7 different arrays to store each "employee" data.
With this logic, I need to split the main list into independent arrays so I can work with them.
How can this be achieved? And also, if I don't have a predefined number of employees (but a defined format :: "Name" followed by 12 months of numbers)...how can I achieve this?
I'm sure I can figure once I get an idea how to "split" a list in different sections -- Every 13 lines?
Yes, at every thirteenth line you'd have the information of an employee.
However, instead of using twelve different lists, you can use a dictionary of lists, so that you wouldn't have to worry about the number of employees.
And you can either use a parameter on the number of lines directed to each employee.
You could do the following:
infile = open("file.txt", "rt")
employee = dict()
name = infile.readline().strip()
while name:
employee[name] = list()
for i in xrange(1, 12):
val = float(infile.readline().strip())
employee[name].append(val)
name = infile.readline().strip()
Some ways to access dictionary entries:
for name, months in employee.items():
print name
print months
for name in employee.keys():
print name
print employee[name]
for months in employee.values():
print months
for name, months in (employee.keys(), employee.values()):
print name
print months
The entire process goes as follows:
infile = open("file.txt", "rt")
employee = dict()
name = infile.readline().strip()
while name:
val = 0.0
for i in xrange(1, 12):
val += float(infile.readline().strip())
employee[name] = val
print ">>> Employee:", name, " -- salary:", str(employee[name])
name = infile.readline().strip()
Sorry for being round the bush, somehow (:
Here is option.
Not good, but still brute option.
summed = 0
with open("file.txt", "rt") as f:
print f.readline() # We print first line (first man)
for line in f:
# then we suppose every line is float.
try:
# convert to float
value = float(line.strip())
# add to sum
summed += value
# If it does not convert, then it is next person
except ValueError:
# print sum for previous person
print summed
# print new name
print line
# reset sum
summed = 0
# on end of file there is no errors, so we print lst result
print summed
since you need more flexibility, there is another option:
data = {} # dict: list of all values for person by person name
with open("file.txt", "rt") as f:
data_key = f.readline() # We remember first line (first man)
data[data_key] = [] # empty list of values
for line in f:
# then we suppose every line is float.
try:
# convert to float
value = float(line.strip())
# add to data
data[data_key].append(value)
# If it does not convert, then it is next person
except ValueError:
# next person's name
data_key = line
# new list
data[data_key] = []
Q: let's say that I want to print a '2% bonus' to employees that made more than 7000 in total sales (12 months)
for employee, stats in data.iteritems():
if sum(stats) > 7000:
print employee + " done 7000 in total sales! need 2% bonus"
I would not create 7 different arrays. I would create some sort of data structure to hold all the relevant information for one employee in one data type (this is python, but surely you can create data structures in python as well).
Then, as you process the data for each employee, all you have to do is iterate over one array of employee data elements. That way, it's much easier to keep track of the indices of the data (or maybe even eliminates the need to!).
This is especially helpful if you want to sort the data somehow. That way, you'd only have to sort one array instead of 7.

Categories