Setup
-
Install python
Install python3 per your OS instructions.
-
Setup a virtual environment with venv
Create the venv:
python -m venv venv
Activate the venv:
source venv/bin/activate
-
Install requirements
Run the following command to install the project’s required libraries:
python -m pip install -r requirements.txt
Module 1
Count Purchases by Category
Verify module:
To run tests run: pytest -k "module1" -s
To run the file: python -m budget.UsingCounter
-
Import the Expense Module
Last month’s spending data is in
data/spending_data.csv
, which is a spreadsheet with 3 columns for - Location, Category, and amount. For example, the first row contains:Alaska Air,Travel,-$115.75
. We want to analyze our spending habits in a few different ways. In this module, we are going to read in this file and display the categories with the most purchases in a graph.To read in the data, we’ll use the classes in the file named Expense.py. There are 2 classes -- Expense (which has a vendor, category, and amount) and Expenses (which has a list of type Expense and a sum of the amounts). Expenses also has a method read_expenses() which we’ll use to read the .csv file.
To start, open the file named
FrequentExpenses.py
in thebudget
directory, and addimport Expense
to the top of the file. -
Read in the Spending Data
Create a variable named expenses and set it equal to calling the Expenses() constructor. Then call the read_expenses() method on expenses and pass in the name of the file
data/spending_data.csv
. -
Create a List of the Spending Categories
Create an empty list called spendingCategories. Then, create a for loop that iterates each Expense in the expenses. Inside the loop, we want to
append()
expense.category
tospendingCategories
. -
Count Categories with a Counter Collection
In order to use the Counter Collection,
import collections
at the top of the file. Then after the for loop, create a new variable calledspendingCounter
and set equal to passingspendingCategories
to thecollections.Counter()
constructor.If you printed the Counter with print(spendingCategories), you would see the following output:
Counter({'Eating Out': 8, 'Subscriptions': 6, 'Groceries': 5, 'Auto and Gas': 5, 'Charity': 2, 'Gear and Clothing': 2, 'Phone': 2, 'Travel': 1, 'Classes': 1, 'Freelance': 1, 'Stuff': 1, 'Mortgage': 1, 'Paycheck': 1, 'Home Improvements': 1, 'Parking': 1, 'Utilities': 1})
You can see it shows the category as the key and the number of times it was used as the value. With ‘Eating Out` as the most common expense which was done 8 times.
-
Get the Top 5 Categories
We can get only the top 5 most common categories by calling the
most_common()
method onspendingCounter
and passing in the value5
. Set the result equal to a variable calledtop5
. -
Convert the Dictionary to 2 Lists
If you’ve used the
zip()
function before it combines 2 iterables (for example, combines two lists into a list of tuples). We can also usezip(*dictionary_variable)
to separate the keys and values of a dictionary into separate lists. Since we want to have 2 separate lists for the categories and their counts for the bar graph, let’s callzip(*top5)
and set the result equal to two variables -categories, count
. -
Plot the Top 5 Most Common Categories
Add
import matplotlib.pyplot as plt
to the top of the file. Then at the end of the file, callfig,ax=plt.subplots()
to initializefig
as the Figure, or top level container for our graph. Andax
as the Axes, which contains the actual figure elements. -
Create the bar chart
Next, call
ax.bar()
with thecategories
andcount
lists as parameters. To add a title, call ax.set_title() and pass in the string '# of Purchases by Category'. -
Display the graph
Finally, to display the graph, call
plt.show()
.The resulting graph should be displayed:
Module 2
Create the BudgetList class to Display Overage Expenses
Verify module:
To run tests run: pytest -k "module2" -s
To run the file: python -m budget.BudgetList
-
Create the BudgetList class
In the
budget
directory, open theBudgetList.py
file. Inside that file, create a class calledBudgetList
with onlypass
inside the class for now. -
Create the constructor
Replace
pass
with a constructor that has two parameters -self, budget
. Then initialize the following class variables:self.budget
to the passed-inbudget
self.sum_expenses
to0
self.expenses
to an empty listself.sum_overages
to0
self.overages
to an empty list
-
Define the append method
Define an append method that has two parameters -
self
anditem
. Putpass
inside the method for now. -
Add items to expenses that are under budget
Replace pass
with an if
statement that checks if self.sum_expenses
plus the passed-in item
is less than self.budget
. Inside the if
block, call append()
on self.expenses
and pass in item
. Also inside the if
block, add item
to self.sum_expenses
.
-
Add items to overages that are over budget
After the if
block, add an else
block that calls append()
on self.overages
and passes in item
. Also, increase self.sum_overages
by item
.
-
Define the len method
Define a method called
__len__
that takes inself
as a parameter. Inside the method, return the sum of the length ofself.expenses
and the length ofself.overages
. -
Define the main function
After the BudgetList class, define a
main() function
. Inside ofmain()
, create amyBudgetList
variable and assign it to calling theBudgetList
constructor with a budget argument of1200
. -
Import the Expense module
Before we can use the Expense class to read in spending data,
import Expense
at the top of BudgetList.py -
Read in the spending data file
Next, create a variable named expenses and set it equal to calling the
Expense.Expenses()
constructor. On the next line, call theread_expenses()
method onexpenses
and pass in the name of the filedata/spending_data.csv
. For this to work, we also need toimport Expense
at the top of the file. -
Add the expenses to the BudgetList
After reading the expenses, create a
for
loop that has an iterator calledexpense
and loops throughexpenses.list
. Inside the for loop, callappend()
, withexpense.amount
as an argument, onmyBudgetList
. -
Print the Length of myBudgetList
Call print() to print out the string 'The count of all expenses: ' concatenated with the length of myBudgList inside the print() call. Hint: Call the len() function with myBudgetList as an argument, then wrap that in a call to str() to convert to a string.
-
Tell Python to run the main function
After the main function, create an
if
statement that checks if__name__
is equal to"__main__"
. If so, callmain()
.Now we can test that append() and len() are working for our BudgetList. Run
python BudgetList.py
and the output should be"The count of all expenses: 37"
.
Module 3
Finish Making BudgetList an Iterable
Verify module:
To run tests run: pytest -k "module3" -s
To run the file: python -m budget.BudgetList
-
Create iter()
Next, we want to create an iterator for BudgetList by implementing iter() and next() to iterate the expenses list first and then continue iterating the overages list. Once those are implemented and you can get an iterator from BudgetList, it will be an iterable. Inside the BudgetList class, at the bottom, define an iter method that has self as a parameter. Put
pass
inside the body of the method for now. -
Finish iter()
Inside
__iter__()
, removepass
and replace it with settingself.iter_e
to calling theiter()
constructor withself.expenses
as an argument. On the next line, setself.iter_o
to calling theiter()
constructor withself.overages
as an argument. Finally to finish the method,return self
. -
Create next()
After the iter method, define the method next() with
self
as a parameter. Putpass
inside the body of the method for now. -
Finish next()
Inside
__next__()
, removepass
and replace it with atry:
block. Inside thetry:
block,return
a call to__next__()
onself.iter__e
. On the next line add an except block, StopIteration as stop as the exception. Inside the except block,return
a call to__next__()
onself.iter__o
. -
Test the iterable
We can now test that BudgetList works as an iterable by using it in a for loop. In main(), after the print statement, create a
for
loop that has an iterator calledentry
and loops throughmyBudgetList
. Inside the for loop, call print() withentry
as an argument.If we run
python BudgetList.py
, the output should be"The count of all expenses: 37"
followed by each of the 37 amounts. -
Import Matplotlib
Now we want to show a bar graph comparing the expenses, overages, and budget totals. First, we need to add
import matplotlib.pyplot as plt
to the top of the file afterimport Expense
. -
Create the figure and axes
Then at the end of main(), call
fig,ax=plt.subplots()
to initializefig
as the Figure, or top level container for our graph. Andax
as the Axes, which contains the actual figure elements. -
Create the list of labels
Create a variable called
labels
and set it equal to a list with the following values:'Expenses', 'Overages', 'Budget'
. -
Create the list of values
Create a variable called
values
and set it equal to a list with the following properties frommyBudgetList
:sum_expenses
,sum_overages
, andbudget
. -
Create the bar graph
Next, call
ax.bar()
with thelabels
andvalues
lists as parameters. -
Set the title
To add a title, call ax.set_title() and pass in the string 'Your total expenses vs. total budget'.
-
Show the figure
Finally, to display the graph, call
plt.show()
.