---
title: "Calculations of income tax are rolling joins"
author: "Hugh Parsonage"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Calculations of income tax are rolling joins}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


## Short introduction to ordinary income tax

```{r loadPackages}
library(knitr)
library(magrittr)
library(data.table)
library(hutils)
library(grattan)
```

Generally, income taxes are parmeterized by tax tables. In Australia, for the 2017-18 financial year, the table looks like

```{r tax-table-201718}
dollar <- function(x) paste0("$", prettyNum(x, big.mark = ","))
grattan:::tax_table2[fy_year == "2017-18",
                     .(`Lower bracket` = dollar(lower_bracket),
                       `Tax payable` = dollar(tax_at),
                       `Marginal rate` = marginal_rate)] %>%
  kable(align = "r")
```

To calculate the income tax for a given income find the next lowest value in the `Lower bracket` column, then add the tax payable and difference between the lower bracket value and the income multiplied by the marginal rate. Originally, we implemented it like this:

```{r}
income <- 50e3
fy_year <- "2017-18"

ifelse(fy_year == '2017-18',
       ifelse(income < 18200,
              0,
              ifelse(income < 37e3,
                     0 + 0.19 * (income - 18200),
                     ifelse(income < 87e3,
                            3572 + 0.325 * (income - 37000),
                            ifelse(income < 180e3,
                                   19822 + 0.37 * (income - 87e3),
                                   54232 + 0.45 * (income - 180e3))))),
       stop("Not yet implemented."))
```

There were some problems, however. One is that it's difficult to update or modify. But perhaps more importantly is that it's not particularly *literate*: the code merely 'happens' to give the right answer, rather than expressing the method too. 

## Income tax calculations are rolling joins

A more natural and expressive approach is to treat the income tax as a rolling join. 

```{r}
input <- data.table(income = income)
tax_table2 <- copy(grattan:::tax_table2)

# Record the order if needed
input[, the_order := .I]
input[, fy_year := "2017-18"]
setkey(input, fy_year, income)

tax_table2[input, roll = TRUE] %>%
  .[, tax := tax_at + (income - lower_bracket) * marginal_rate] %>%
  .[order(the_order)]
```

With this approach, we can just append new tax years or proposed tax rates to `tax_table2`, rather than pipetting magic numbers into a nest of `ifelse`s. The code and the data are separate and both are easier to manage. 
