Categories
level 1 python

Expense Tracker in Python – Level 1

Expense tracking is a common task used in every industry. In this post, we’re going to build a simple expense tracker in Python for exercise. This Python expense tracker will simply track your expenses in a CSV file. By the end of this tutorial, you’ll have a Python expense tracking program that shows you your expenses and allows you to add to the tracker.

In this post, we’ll cover:

  • Reading Expenses from a CSV File in Python
  • Writing to Your Python Expense Tracker
  • Seeing and Adding to Your Expenses
  • Summary of How to Build a Python Expense Tracker

Find this project on GitHub.

Reading Expenses from a CSV File in Python

We could start with a function to read from or write to the CSV file that we’re using to track our expenses. For this tutorial, I chose to start with reading expenses. First things first, we import the csv library. 

Our read_expenses function doesn’t need any parameters. We’re hard-coding in the name of our expense file. This means we need to make sure that we run this program in the same folder that we have the program code and the CSV file.

First, we try to open the expenses.csv file and create a CSV reader. Next, we declare an empty list that represents the expenses. We use the CSV reader to add all the rows of the expense tracker to the list of expenses. 

Now, we print out our expenses. Notice the comment there that denotes the way that the expenses are written. This column format has to be followed for both the expense reader and writer. We show the user that on a certain date, they spend the cost on the category.

If there is no expenses.csv file, we simply print out that the file doesn’t exist and move on.

import csv
 
def read_expenses():
      try:
       with open("expenses.csv", "r") as f:
           csv_reader = csv.reader(f, delimiter=",")
           expenses = []
           for row in csv_reader:
               expenses.append(row)
       # expenses come in the columns of date (0), category (1), price (2)
       for line in expenses:
           print(f"On {line[0]}, {line[2]} was spent on {line[1]}")
   except:
       print("No Expense Tracker File Exists Yet")

Writing to Your Python Expense Tracker

Now that we’ve created a function to read from our expense tracker, let’s create a function to write to it. Our write_expenses function executes a while loop while we are reporting expenses. To do this, we start with a reporting variable that we set to True and then open up the expenses file in append mode and create a CSV writer with it.

While we are reporting, we ask the user to input the date, category, and cost. We write this data that the user input into the expense tracker. Once we write the data in, we ask the user if they are done reporting. If they are, then we set our reporting variable to False to end the while loop. Finally, we close the file.

def write_expenses():
   reporting = True
   f = open("expenses.csv", "a")
   expense_writer = csv.writer(f, delimiter=",")
   while reporting:
       date = input("What date was the expense incurred? ")
       category = input("What category is the expense for? ")
       cost = input("How much money did you spend? ")
       expense_writer.writerow([date, category, cost])
       end = input("If you are done inputting expenses, type \"end\" ")
       if end == "end":
           reporting = False
 
   f.close()

Seeing and Adding to Your Expenses

Now it’s time to put the reading and writing functions together. First we tell the user that we’re going to show them the current state of the expense report. Then, we call the read_expenses function we made earlier. 

After showing them the current expense tracker (or the fact that it doesn’t exist), we ask the user if they want to report expenses. If they do, then we call the write_expense function we made.

print("Current state of expense report: ")
read_expenses()
report = input("Would you like to report expenses?(y/n) ")
if report == "y":
   write_expenses()

Starting from no expense tracker file, this is what an expense report would look like when we run the program.

After we put in the initial expenses, we can run the program again and see that all our expenses were saved and we can continue to report expenses if we’d like.

Summary of How to Build a Python Expense Tracker

In this post we learned how to build a simple CSV expense tracker in Python. We made two functions to encapsulate the reading and writing to a CSV functionality of our expense tracker. Then, we wrote a few lines of Python to run the program as a script. Our Python expense tracker shows you the date you made the expenditure, the category that you spent on, and the amount you spent.

Categories
General Python python starter projects

Super Simple Python: Unit Convertor

Super Simple Python is a series of Python projects you can do in under 15 minutes. In this episode, we’ll be covering how to build a simple unit convertor in under 25 lines of Python!

For a video version:

Unit conversion is annoying for humans at best, but very simple for machines. If you went to school in America, you probably wasted a year of science class learning how to do unit conversions. We’re going to build a unit convertor in Python in much the same way we built the Super Simple Python Calculator. We’ll build a set of functions and then use a dictionary to map strings to those functions.

Unit Convertor Functions

In the video I only gave four functions, but in this example, I’ll give six. We’ll do inches to feet, miles to kilometers, celsius to fahrenheit, and all the reverses. Each of these functions is pretty self-explanatory by name. They will each take one parameter – the value in the base unit – and return the value in the converted to unit. Each function will just do some math on the passed in value to convert the unit over.

def in_to_ft(_in):
    return _in/12
 
def ft_to_in(_ft):
    return _ft*12
 
def mi_to_km(_mi):
    return _mi*1.609
 
def km_to_mi(_km):
    return _km/1.609
 
def c_to_f(_c):
    return 9*_c/5 + 32
 
def f_to_c(_f):
    return (_f-32)*5/9

Mapping the Functions

Much like we did with the calculator function we will now map the functions. Thanks to the way Python is built as a language, we can map strings to functions in a dictionary. Let’s create a dictionary that will take a string of plain English as a key and map that to a function as a value. We made six functions earlier so our dictionary will have six entries.

_dict = {
    "inches to feet": in_to_ft,
    "feet to inches": ft_to_in,
    "miles to kilometers": mi_to_km,
    "kilometers to miles": km_to_mi,
    "celsius to fahrenheit": c_to_f,
    "fahrenheit to celsius": f_to_c    
}

Doing the Unit Conversion

Now that we’ve set up our functions and our mapping, all we have to do is perform the unit conversion. First we’ll tell the user which conversions are available. Then, we’ll ask them which conversion they want to do. We will also need to get the value of the base unit from the user. Notice that I wrap the input() in a float() for getting the base value. This is to convert the inputted string value into a float. Once everything is set up, we simply call the dictionary to get our unit convertor function and print out the converted value.

print("Available conversions (to and from): inches to feet, miles to kilometers, celsius to fahrenheit")
convert = input("Which conversion do you want to do? ")
num = float(input("What is the value in the base unit? "))
 
op = _dict[convert]
print(op(num))

When we run our program, we should see something like the image below.

I run this site to help you and others like you find cool projects and practice software skills. If this is helpful for you and you enjoy your ad free site, please help fund this site by donating below! If you can’t donate right now, please think of us next time.

Categories
APIs General Python

Climate Mentions in the News? Shockingly Low

I don’t know about you, but as someone who lives on planet Earth, I believe that the climate crisis is an issue that needs to be solved. Personally, I would like to solve it through building more renewables as I outline on my climate blog. Since the climate crisis has been a pressing issue for the last, oh I don’t know, 50 years? 60 years? I’d expect that there’d be a good amount of news about climate related topics. I didn’t know, but I decided to find out.

To do this, I used the New York Times Archive API and pulled the headlines of articles from 2008 to 2021. For a detailed explanation of how to use the New York Times Archive API to download archived news headlines, please see How to Download Archived News HeadlinesFor those of you uninterested in the code, skip directly to the findings.

Checking Titles for Mentions of Climate

At this point, I’m going to assume that you’ve already downloaded all the data from the NY Times archive API into JSON format as I outlined in the article above. The first thing we’ll do for our project to track mentions of climate in the news over time is create a function that will extract the headlines for each month. To get started we’ll have to import the json library and the month_dict we created in the link on how to download archived titles above. It’s a relatively simple dictionary with the month number as the key and the month name as the value.

import json
from archive import month_dict

Now let’s make a function that checks each headline for mentions of the climate. This function will take two parameters, the year and the month that we’re interested in. The first thing we’ll do is open up our file and store the JSON information into a dictionary titled entries. We’ll enclose this in a try/except block just in case the file doesn’t exist. Next, we’ll save the length of our entries as total_headlines which represents the total number of news headlines in that month. From here we’ll start off our count, which I’m storing in a variable called cc for “climate count”, at 0. As we loop through each headline in the entry, if the headline contains the word “climate” we’ll increment cc by one. At the end, we’ll return a tuple of the total number of headlines and the count of the number of headlines that contain the word “climate”.

# checks headlines for climate change
def cc_finder(year, month):
    filename = f"{year}/{month_dict[month]}.json"
    try:
        with open(filename, "r") as f:
            entries = json.load(f)
    except:
        print("No such file")
        return
    # get every headline
    # check if it has climate change in it
    total_headlines = len(entries)
    # print(total_headlines)
    cc = 0
    for entry in entries:
        headline = entry['headline']['main']
        if "climate" in headline.lower():
            cc += 1
    # print(cc)
    return (total_headlines, cc)

Alright now that we’ve created a function to return the number of articles per month and the number of article headlines containing the word “climate” over time, let’s graph our findings. By the way, it’s not necessary to return this as a tuple, we could also just return the proportion, but I’ve chosen to return it as a tuple because I’d like to actually see the numerical comparisons as well. Now let’s take a look at how we can graph our findings.

Create the Function to Graph How Often Climate is Mentioned in the News

We’ll define a function, graph_cc that stands for “graph climate count”. I graph three figures here, but if you only care about the first one, simply replace the ratio.show() line with plt.show() and feel free to delete the rest of the code. I’ve already downloaded all the data for the years 2008 through November (so far) of 2021. Since we’re only a few days into November let’s keep in mind that the article counts for November will be low. Also, since it is around COP26 right now, we should expect a higher ratio and count for climate articles, and we’ll come back to this again in a few months to investigate if the numbers are artificially inflated or not.

In our function we’ll start by creating a list of years that will contain the years 2008 through 2022. I’ve defined four lists, xs is the x values that represent months since January 2008 (starting at 0), ys is the y values that are in ratio form, ys_total is the y values for total number of articles in a month, and ys_cc is the values for total number of articles containing the word ‘climate’ in that month. We also have a variable called months_since_2008 that we increment every time we loop through a month. Then we set up a nested for loop to loop through each month for all the years we defined in our year list and get all the x and y values we need. Finally, we plot each of our findings. Notice that I end with an input() statement, that’s to keep the program running long enough to actually see the plots.

def graph_cc():
    years = list(range(2008, 2022))
    xs = []
    ys = []
    ys_total = []
    ys_cc = []
    months_since_2008 = 0
    for year in years:
        for i in range(1,13):
            if year == 2021 and i > 11:
                continue
            total, cc = cc_finder(year, i)
            ratio = cc/total
            xs.append(months_since_2008)
            months_since_2008 += 1
            ys.append(ratio)
            ys_total.append(total)
            ys_cc.append(cc)
       
    ratio = plt.figure(1)
    plt.plot(xs, ys)
    plt.xlabel("Months since January 2008")
    plt.ylabel("Proportion of News Headlines about Climate")
    plt.title("Climate in the News Over Time")
    plt.show()
 
    total = plt.figure(2)
    plt.plot(xs, ys_total)
    plt.xlabel("Months since January 2008")
    plt.ylabel("Total Number of Articles per Month")
    plt.title("Number of NY Times Articles per Month over Time")
    total.show()
 
    cc = plt.figure(3)
    plt.plot(xs, ys_cc)
    plt.xlabel("Months since January 2008")
    plt.ylabel("Total Number of Articles Mentioning Climate")
    plt.title("Number of NY Times Articles Mentioning Climate per Month over Time")
    cc.show()
 
    input()

Climate In the News Over Time: Graphed Findings

Once we run this we should see the following plot: (I’ll leave the other two to the appendix)

This is both disheartening and quite interesting. We can see that climate has gotten almost no mentions in the news since 2008 up until literally October of 2021. The average is around 0.004 over this time when we include the last couple months. That’s INSANE! That means, on average, less than half a percent of news (NY Times anyway) articles in the last 13 years have mentioned climate. THIS IS THE MOST IMPORTANT ISSUE OF OUR GENERATION! I’ve included the last two graphs after this, but like WHAT IN THE WORLD?? HOW? WHY? We need to focus more on climate change and how to fight it, and for that, we’ll need the media’s help.

I run this site to help you and others like you find cool projects and practice software skills. If this is helpful for you and you enjoy your ad free site, please help fund this site by donating below! If you can’t donate right now, please think of us next time.

Appendix (the other two images)

These other two images are kind of interesting too, but I wanted to wrap up after showing the ratio of climate news to total news because that’s CRAZY to me. The number of NY Times news articles per month have been trending down over time, who knew? Also, there was a weird dip between 2010 and 2012, I wonder why? I’ll have to do some snooping to find out. One slightly positive note is that it does look like even though the total number of articles per month have been trending down, the number of climate articles have remained relatively consistent and are even currently trending up!