-
Install python3 per your OS instructions.
-
Create the venv:
python -m venv venvActivate the venv:
source venv/bin/activate -
Run the following command to install the project’s required libraries:
python -m pip install -r requirements.txt
To run tests run: pytest -k "module1" -s
To run the file: python -m budget.UsingCounter
-
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.pyin thebudgetdirectory, and addimport Expenseto the top of the file. -
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 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.categorytospendingCategories. -
In order to use the Counter Collection,
import collectionsat the top of the file. Then after the for loop, create a new variable calledspendingCounterand set equal to passingspendingCategoriesto 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.
-
We can get only the top 5 most common categories by calling the
most_common()method onspendingCounterand passing in the value5. Set the result equal to a variable calledtop5. -
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. -
Add
import matplotlib.pyplot as pltto the top of the file. Then at the end of the file, callfig,ax=plt.subplots()to initializefigas the Figure, or top level container for our graph. Andaxas the Axes, which contains the actual figure elements. -
Next, call
ax.bar()with thecategoriesandcountlists as parameters. To add a title, call ax.set_title() and pass in the string '# of Purchases by Category'. -
Finally, to display the graph, call
plt.show().The resulting graph should be displayed:
To run tests run: pytest -k "module2" -s
To run the file: python -m budget.BudgetList
-
In the
budgetdirectory, open theBudgetList.pyfile. Inside that file, create a class calledBudgetListwith onlypassinside the class for now. -
Replace
passwith a constructor that has two parameters -self, budget. Then initialize the following class variables:self.budgetto the passed-inbudgetself.sum_expensesto0self.expensesto an empty listself.sum_overagesto0self.overagesto an empty list
-
Define an append method that has two parameters -
selfanditem. Putpassinside the method for now.
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.
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 a method called
__len__that takes inselfas a parameter. Inside the method, return the sum of the length ofself.expensesand the length ofself.overages. -
After the BudgetList class, define a
main() function. Inside ofmain(), create amyBudgetListvariable and assign it to calling theBudgetListconstructor with a budget argument of1200. -
Before we can use the Expense class to read in spending data,
import Expenseat the top of BudgetList.py -
Next, create a variable named expenses and set it equal to calling the
Expense.Expenses()constructor. On the next line, call theread_expenses()method onexpensesand pass in the name of the filedata/spending_data.csv. For this to work, we also need toimport Expenseat the top of the file. -
After reading the expenses, create a
forloop that has an iterator calledexpenseand loops throughexpenses.list. Inside the for loop, callappend(), withexpense.amountas an argument, onmyBudgetList. -
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.
-
After the main function, create an
ifstatement 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.pyand the output should be"The count of all expenses: 37".
To run tests run: pytest -k "module3" -s
To run the file: python -m budget.BudgetList
-
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
passinside the body of the method for now. -
Inside
__iter__(), removepassand replace it with settingself.iter_eto calling theiter()constructor withself.expensesas an argument. On the next line, setself.iter_oto calling theiter()constructor withself.overagesas an argument. Finally to finish the method,return self. -
After the iter method, define the method next() with
selfas a parameter. Putpassinside the body of the method for now. -
Inside
__next__(), removepassand replace it with atry:block. Inside thetry:block,returna call to__next__()onself.iter__e. On the next line add an except block, StopIteration as stop as the exception. Inside the except block,returna call to__next__()onself.iter__o. -
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
forloop that has an iterator calledentryand loops throughmyBudgetList. Inside the for loop, call print() withentryas 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. -
Now we want to show a bar graph comparing the expenses, overages, and budget totals. First, we need to add
import matplotlib.pyplot as pltto the top of the file afterimport Expense. -
Then at the end of main(), call
fig,ax=plt.subplots()to initializefigas the Figure, or top level container for our graph. Andaxas the Axes, which contains the actual figure elements. -
Create a variable called
labelsand set it equal to a list with the following values:'Expenses', 'Overages', 'Budget'. -
Create a variable called
valuesand set it equal to a list with the following properties frommyBudgetList:sum_expenses,sum_overages, andbudget. -
Next, call
ax.bar()with thelabelsandvalueslists as parameters. -
To add a title, call ax.set_title() and pass in the string 'Your total expenses vs. total budget'.
-
Finally, to display the graph, call
plt.show().