Marginal Tax Calculator

This is probably the easiest application I've ever written that drove me mad. For the longest time I could not figure out how it was possible to pay negative taxes with this application. Then when I figured out what I did wrong to cause that problem, I had other problems that arose. Either way in order to make this article possible it had to be refactored. The nice part about how I wrote this application is that the tax brackets and tax rates are stored in a csv file. It should be possible to calculate a marginal tax rate at any rate and any bracket provided it can be supported by your system's memory. If you don't like my rates or brackets you can change them without writing a single line of code too. Let's see whats going on to make it run.

The first step as always is to figure out what values we want to get, and take in user input. I went a little overkill on all the variables, but it made the code a little more readable. I treated brackets and rates as lists because that makes it easier to make this application modular. bracket1, bracket2, bracket3 would have been ugly, and more static than a list. Then just so the user knows what information we're working with I output their annual income before doing any calculations. When you use .format in Python to format strings, {} are place keepers for variables within the parentheses of .format(). You'll see what I mean below, and it's how I recommend handling variables. Concatenation is common in other languages, but sometimes it requires casting. Not only can you get around that with format in Python, but you can limit decimal points when you use floats. Do not be like I typically am and create more work for yourself.

initialize variables and create empty arrays

The next step from here is to process the file with tax brackets and rates. Python has a special csv library for reading csv files that lets you skip the headers (top row with column titles). It's worth noting that the keyword "with" automatically closes the file once processing with the file is complete. It's important to close the file when you're done with it to avoid performance issues such as crashing or making unintended edits. You can call the "close()" method by chaining it to the filename with a period, but the keyword "with" is safer.

Anyway, I use a for loop to separate each line by the delimiter which in this case a comma. The acronym stands for "comma separated values," because all of the important values are separated by only commas. Once that is done the split function will put both values into a list. The first value of the csv is in thousands, and needs to be converted from string to float. The conversion can be done casting the string into a float, and its value properly represented by multiplying it by 1000. From there it's important to remember that any multi-line file will have a hidden character called a 'newline' character, or '\n'. If this character is not removed it will cause issues for this program. Thankfully Python has a method that removes '\n' characters called rstrip(). Since the rate is already in decimal format the only work that needs to be done is to add it to the appropriate list.

open the file and process the brackets and rates

Once all that work is completed the final step is to finally do the calculation. I am going to assume that the first bracket will always be a rate of 0.00. That means it does not make sense to try to do math on anything up to that amount, however keeping track of that dollar amount is important for calculation later on. Particularly, it tells us how much income is not taxed. Since we know that we can automatically move up one bracket before we start doing our math. We also want to define the end point for simplicity, and typically that will always be the length of the list minus 1. List indices are 0-based, but length is 1-based, which means the length will always be 1 number higher than the last index. Then as we do our calculations we want to make sure we do not try to go beyond the list, and we always keep our taxable amount within the specified range.

The loop itself then removes the entire amount from the last bracket from the amount of money to be taxed. Then it subtracts that amount from the total income amount, and multiplies the result of that subtraction by the current rate. The income after the taxes are applied is equal to the total income - taxes paid. Then I increment the index again to move into a higher bracket, and keep going until I have hit the highest bracket. The structure of the program is simple, but there are some easy to miss pitfalls.

main loop that performs the incremental calculation for each bracket and rate

This was probably the most frustrating easy application I ever wrote. There's so many things that can go wrong when making it modular that are nearly impossible to diagnose. It was a nice exercise in processing csv data automatically, and data validation. You can grab both the script and csv file, check this all out in a single Jupyter Notebook page, or see the video below for a demonstration.