import pandas as pd #for data manipulation
import pandas_datareader as pdr #to upload online datasets
from pandas_datareader import data, wb
import matplotlib.pyplot as plt #for visualization
import datetime as dt #to work with datetime objects
codes = ['W006RC1Q027SBEA','B075RC1Q027SBEA','A074RC1Q027SBEA','A053RC1Q027SBEA','CP','MEHOINUSA672N'] #FRED source codes
start = dt.datetime(2000,1,1) #the start date for my data
taxRev = data.DataReader(codes,'fred',start) #importing data from FRED
taxRev.rename(columns={'W006RC1Q027SBEA':'Tax_Revenue','B075RC1Q027SBEA':'Corporate_Tax','A074RC1Q027SBEA':'Personal_Tax','A053RC1Q027SBEA':'Corporate_BTProfit','CP':'Corporate_ATProfit','MEHOINUSA672N':'RMed_Household_Income'},inplace=True)
taxRev.head()
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | |
---|---|---|---|---|---|---|
DATE | ||||||
2000-01-01 | 1272.073 | 202.205 | 976.598 | 770.883 | 527.619 | 61399.0 |
2000-04-01 | 1284.187 | 201.051 | 986.846 | 761.520 | 519.852 | NaN |
2000-07-01 | 1291.650 | 185.570 | 1011.109 | 736.092 | 513.338 | NaN |
2000-10-01 | 1306.215 | 187.559 | 1023.905 | 717.789 | 491.848 | NaN |
2001-01-01 | 1301.000 | 154.940 | 1050.979 | 717.433 | 528.870 | 60038.0 |
taxRev['Personal_Revenue_Change'] = taxRev['Personal_Tax'].pct_change() #calculates growth rates
taxRev['Corporate Revenue Change'] = taxRev['Corporate_Tax'].pct_change()
taxRev.head()
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | Personal_Revenue_Change | Corporate Revenue Change | |
---|---|---|---|---|---|---|---|---|
DATE | ||||||||
2000-01-01 | 1272.073 | 202.205 | 976.598 | 770.883 | 527.619 | 61399.0 | NaN | NaN |
2000-04-01 | 1284.187 | 201.051 | 986.846 | 761.520 | 519.852 | NaN | 0.010494 | -0.005707 |
2000-07-01 | 1291.650 | 185.570 | 1011.109 | 736.092 | 513.338 | NaN | 0.024586 | -0.077000 |
2000-10-01 | 1306.215 | 187.559 | 1023.905 | 717.789 | 491.848 | NaN | 0.012655 | 0.010718 |
2001-01-01 | 1301.000 | 154.940 | 1050.979 | 717.433 | 528.870 | 60038.0 | 0.026442 | -0.173913 |
taxRev['Corporate_Tax_Roll'] = taxRev['Corporate_Tax'].rolling(4).mean() #calculates one year rolling average
taxRev['Personal_Tax_Roll'] = taxRev['Personal_Tax'].rolling(4).mean()
taxRev
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | Personal_Revenue_Change | Corporate Revenue Change | Corporate_Tax_Roll | Personal_Tax_Roll | |
---|---|---|---|---|---|---|---|---|---|---|
DATE | ||||||||||
2000-01-01 | 1272.073 | 202.205 | 976.598 | 770.883 | 527.619 | 61399.0 | NaN | NaN | NaN | NaN |
2000-04-01 | 1284.187 | 201.051 | 986.846 | 761.520 | 519.852 | NaN | 0.010494 | -0.005707 | NaN | NaN |
2000-07-01 | 1291.650 | 185.570 | 1011.109 | 736.092 | 513.338 | NaN | 0.024586 | -0.077000 | NaN | NaN |
2000-10-01 | 1306.215 | 187.559 | 1023.905 | 717.789 | 491.848 | NaN | 0.012655 | 0.010718 | 194.09625 | 999.61450 |
2001-01-01 | 1301.000 | 154.940 | 1050.979 | 717.433 | 528.870 | 60038.0 | 0.026442 | -0.173913 | 182.28000 | 1018.20975 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2019-01-01 | 2018.649 | 136.606 | 1687.966 | 2015.490 | 1800.048 | NaN | 0.033116 | -0.057064 | 146.72275 | 1640.88925 |
2019-04-01 | 2027.559 | 145.976 | 1691.305 | 2084.921 | 1859.741 | NaN | 0.001978 | 0.068591 | 145.91275 | 1660.35275 |
2019-07-01 | 2028.389 | 130.051 | 1698.354 | 2045.955 | 1836.638 | NaN | 0.004168 | -0.109093 | 139.37650 | 1677.87100 |
2019-10-01 | 2065.410 | 140.738 | 1718.858 | 2126.524 | 1903.753 | NaN | 0.012073 | 0.082175 | 138.34275 | 1699.12075 |
2020-01-01 | NaN | NaN | 1721.615 | NaN | NaN | NaN | 0.001604 | 0.000000 | NaN | 1707.53300 |
81 rows × 10 columns
fig, ax = plt.subplots(figsize=(15,5)) #graph construction
tcja = dt.datetime(2017,12,22)
ax.plot(taxRev.index, taxRev['Corporate_BTProfit'],color='red')
ax.plot(taxRev.index, taxRev['Corporate_ATProfit'],color='black')
ax.plot(taxRev.index, taxRev['Corporate_Tax'],color='red',alpha=0.5)
ax.axvline(tcja,color='gray',linewidth=1)
ax.legend(['Corporate Profits Before Tax','Corporate Profits After Tax','Corporate Tax Revenue'],frameon=False)
ax.set_ylabel('Profit in $billions')
ax.set_title('Corporate Profits Before and After Tax: 2000-Present')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.annotate('TCJA Signed',xy=(tcja,800),xytext=(dt.datetime(2016,4,30),800))
plt.savefig('corp_profits_b+a.png')
taxRev['Tax_Charge'] = taxRev['Corporate_BTProfit'] - taxRev['Corporate_ATProfit'] #calculates tax expense (slightly different numbers than the tax revenue data, more consistent for this method)
taxRev.head()
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | Personal_Revenue_Change | Corporate Revenue Change | Corporate_Tax_Roll | Personal_Tax_Roll | Tax_Charge | |
---|---|---|---|---|---|---|---|---|---|---|---|
DATE | |||||||||||
2000-01-01 | 1272.073 | 202.205 | 976.598 | 770.883 | 527.619 | 61399.0 | NaN | NaN | NaN | NaN | 243.264 |
2000-04-01 | 1284.187 | 201.051 | 986.846 | 761.520 | 519.852 | NaN | 0.010494 | -0.005707 | NaN | NaN | 241.668 |
2000-07-01 | 1291.650 | 185.570 | 1011.109 | 736.092 | 513.338 | NaN | 0.024586 | -0.077000 | NaN | NaN | 222.754 |
2000-10-01 | 1306.215 | 187.559 | 1023.905 | 717.789 | 491.848 | NaN | 0.012655 | 0.010718 | 194.09625 | 999.61450 | 225.941 |
2001-01-01 | 1301.000 | 154.940 | 1050.979 | 717.433 | 528.870 | 60038.0 | 0.026442 | -0.173913 | 182.28000 | 1018.20975 | 188.563 |
taxRev['effective'] = taxRev['Tax_Charge'] / taxRev['Corporate_BTProfit'] #calculates effective tax rate
taxRev.head()
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | Personal_Revenue_Change | Corporate Revenue Change | Corporate_Tax_Roll | Personal_Tax_Roll | Tax_Charge | effective | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
DATE | ||||||||||||
2000-01-01 | 1272.073 | 202.205 | 976.598 | 770.883 | 527.619 | 61399.0 | NaN | NaN | NaN | NaN | 243.264 | 0.315565 |
2000-04-01 | 1284.187 | 201.051 | 986.846 | 761.520 | 519.852 | NaN | 0.010494 | -0.005707 | NaN | NaN | 241.668 | 0.317350 |
2000-07-01 | 1291.650 | 185.570 | 1011.109 | 736.092 | 513.338 | NaN | 0.024586 | -0.077000 | NaN | NaN | 222.754 | 0.302617 |
2000-10-01 | 1306.215 | 187.559 | 1023.905 | 717.789 | 491.848 | NaN | 0.012655 | 0.010718 | 194.09625 | 999.61450 | 225.941 | 0.314774 |
2001-01-01 | 1301.000 | 154.940 | 1050.979 | 717.433 | 528.870 | 60038.0 | 0.026442 | -0.173913 | 182.28000 | 1018.20975 | 188.563 | 0.262830 |
fig, ax = plt.subplots(figsize=(15,5))
tcja = dt.datetime(2017,12,22)
ax.plot(taxRev.index, taxRev['effective'],color='purple')
ax.axvline(tcja,color='gray',linewidth=1)
ax.set_ylabel('Tax Rate')
ax.set_title('Corporate Effective Tax Rates: 2000-Present')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.annotate('TCJA Signed',xy=(tcja,0.2),xytext=(dt.datetime(2018,3,30),0.2))
plt.savefig('effective_tax.png')
taxRev['Corp Profit Change'] = taxRev['Corporate_ATProfit'].pct_change()
taxRev['Corporate_TaxChange_Roll'] = taxRev['Corporate Revenue Change'].rolling(4).mean()
taxRev['CorpProfChange_Roll'] = taxRev['Corp Profit Change'].rolling(4).mean()
taxRev
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | Personal_Revenue_Change | Corporate Revenue Change | Corporate_Tax_Roll | Personal_Tax_Roll | Tax_Charge | effective | Corp Profit Change | Corporate_TaxChange_Roll | CorpProfChange_Roll | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DATE | |||||||||||||||
2000-01-01 | 1272.073 | 202.205 | 976.598 | 770.883 | 527.619 | 61399.0 | NaN | NaN | NaN | NaN | 243.264 | 0.315565 | NaN | NaN | NaN |
2000-04-01 | 1284.187 | 201.051 | 986.846 | 761.520 | 519.852 | NaN | 0.010494 | -0.005707 | NaN | NaN | 241.668 | 0.317350 | -0.014721 | NaN | NaN |
2000-07-01 | 1291.650 | 185.570 | 1011.109 | 736.092 | 513.338 | NaN | 0.024586 | -0.077000 | NaN | NaN | 222.754 | 0.302617 | -0.012530 | NaN | NaN |
2000-10-01 | 1306.215 | 187.559 | 1023.905 | 717.789 | 491.848 | NaN | 0.012655 | 0.010718 | 194.09625 | 999.61450 | 225.941 | 0.314774 | -0.041863 | NaN | NaN |
2001-01-01 | 1301.000 | 154.940 | 1050.979 | 717.433 | 528.870 | 60038.0 | 0.026442 | -0.173913 | 182.28000 | 1018.20975 | 188.563 | 0.262830 | 0.075271 | -0.061476 | 0.001539 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2019-01-01 | 2018.649 | 136.606 | 1687.966 | 2015.490 | 1800.048 | NaN | 0.033116 | -0.057064 | 146.72275 | 1640.88925 | 215.442 | 0.106893 | -0.015322 | -0.002644 | -0.004911 |
2019-04-01 | 2027.559 | 145.976 | 1691.305 | 2084.921 | 1859.741 | NaN | 0.001978 | 0.068591 | 145.91275 | 1660.35275 | 225.180 | 0.108004 | 0.033162 | -0.003547 | 0.001003 |
2019-07-01 | 2028.389 | 130.051 | 1698.354 | 2045.955 | 1836.638 | NaN | 0.004168 | -0.109093 | 139.37650 | 1677.87100 | 209.317 | 0.102308 | -0.012423 | -0.042514 | -0.002512 |
2019-10-01 | 2065.410 | 140.738 | 1718.858 | 2126.524 | 1903.753 | NaN | 0.012073 | 0.082175 | 138.34275 | 1699.12075 | 222.771 | 0.104758 | 0.036542 | -0.003848 | 0.010490 |
2020-01-01 | NaN | NaN | 1721.615 | NaN | NaN | NaN | 0.001604 | 0.000000 | NaN | 1707.53300 | NaN | NaN | 0.000000 | 0.010418 | 0.014320 |
81 rows × 15 columns
fig, ax = plt.subplots(figsize=(15,5))
ax.plot(taxRev.index, taxRev['CorpProfChange_Roll'],color='red')
ax.plot(taxRev.index, taxRev['Corporate_TaxChange_Roll'],color='purple',alpha=.75)
ax.axhline(color='gray')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_title('Growth Rates of Corporate Tax Revenue vs. Before Tax Profit: 2000-Present')
ax.set_ylabel('Growth Rate')
ax.legend(['1-Year Rolling Corporate Profit Growth Rate','1-Year Rolling Corporate Tax Revenue Growth Rate'],frameon=False)
plt.savefig('corp_growthrates.png')
##ax.axvline(dt.datetime(2017,12,22),color='black',linewidth=1.5)
individual = taxRev.resample('y').mean() #converting quarterly data to yearly
individual['Household_income_change'] = individual['RMed_Household_Income'].pct_change()
individual.tail()
Tax_Revenue | Corporate_Tax | Personal_Tax | Corporate_BTProfit | Corporate_ATProfit | RMed_Household_Income | Personal_Revenue_Change | Corporate Revenue Change | Corporate_Tax_Roll | Personal_Tax_Roll | Tax_Charge | effective | Corp Profit Change | Corporate_TaxChange_Roll | CorpProfChange_Roll | Household_income_change | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DATE | ||||||||||||||||
2016-12-31 | 2019.39000 | 311.86325 | 1546.54425 | 2117.43275 | 1739.83800 | 61779.0 | 0.003899 | 0.010894 | 311.811438 | 1539.729875 | 377.59475 | 0.178377 | 0.021340 | -0.010924 | 0.000732 | 0.031352 |
2017-12-31 | 2019.16275 | 251.49725 | 1613.10275 | 2132.96400 | 1813.55225 | 62626.0 | 0.011401 | -0.057249 | 275.587438 | 1586.580500 | 319.41175 | 0.149865 | -0.015488 | -0.048947 | 0.010969 | 0.013710 |
2018-12-31 | 1956.08100 | 147.36325 | 1620.23100 | 2063.48075 | 1843.71300 | 63179.0 | -0.001901 | -0.091294 | 184.400250 | 1621.182562 | 219.76775 | 0.106480 | 0.024634 | -0.101672 | 0.006878 | 0.008830 |
2019-12-31 | 2035.00175 | 138.34275 | 1699.12075 | 2068.22250 | 1850.04500 | NaN | 0.012834 | -0.003848 | 142.588688 | 1669.558437 | 218.17750 | 0.105491 | 0.010490 | -0.013138 | 0.001017 | 0.000000 |
2020-12-31 | NaN | NaN | 1721.61500 | NaN | NaN | NaN | 0.001604 | 0.000000 | NaN | 1707.533000 | NaN | NaN | 0.000000 | 0.010418 | 0.014320 | 0.000000 |
fig, ax = plt.subplots(figsize=(15,5))
tcja = dt.datetime(2017,12,22)
ax.plot(taxRev.index, taxRev['Personal_Tax_Roll'],color='blue')
ax.plot(taxRev.index, taxRev['Personal_Tax'],color='blue',alpha=.25)
ax.axvline(tcja,color='gray',linewidth=1)
ax.legend(['1-Year Moving Average Personal Tax','Personal Tax Revenue'],frameon=False)
ax.set_ylabel('Tax Revenue in $billions')
ax.set_title('Personal Tax Revenue: 2000-Present')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.annotate('TCJA Signed',xy=(tcja,800),xytext=(dt.datetime(2016,4,30),800))
plt.savefig('personal_taxrev.png')
fig, ax = plt.subplots(figsize=(15,5))
ax.plot(individual.index, individual['Household_income_change'],color='black',alpha=.75)
ax.plot(individual.index, individual['Personal_Revenue_Change'],color='blue')
ax.axhline(color='gray')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_title('Growth Rates of Personal Tax Revenue vs. Household Income: 2000-Present')
ax.set_ylabel('Growth Rate')
ax.legend(['Annual Household Income Growth Rate','Annual Individual Tax Revenue Growth Rate'],frameon=False)
plt.savefig('personal_growth.png')
##ax.axvline(dt.datetime(2017,12,22),color='black',linewidth=1.5)
fig, ax = plt.subplots(figsize=(15,5)) #not included in paper, just for reference
ax.plot(individual.index, individual['RMed_Household_Income'],color='black',alpha=.75)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.set_title('Growth Rates of Personal Tax Revenue vs. Household Income: 2000-Present')
ax.set_ylabel('Growth Rate')
ax.legend(['Annual Household Income Growth Rate','Annual Individual Tax Revenue Growth Rate'],frameon=False)
<matplotlib.legend.Legend at 0x11b42de50>