Andrew Leach
Andrew Leach

Reputation: 167

Loss carry forward with dplyr and mutate

I am working on a tax model in R and I need to do a loss carry-forward, and I'm struggling for how to do it without another (!) loop in my code. Perhaps you have a suggestion?

Reproducible example below:

taxable_income<-c(-10,-10,-10,-10,-10,20,20,20,20,20) #define taxable income amounts
data_test<-data.frame(taxable_income) #put into data frame
data_test$carry_fwd<-0 #initialize carry forward and tax payable columns
data_test$tax_payable<-0
tax_rate<-0.27 #tax rate of 27%
#what I would like to be able to do is conditionally carry-forward a loss so that I end up with the following:
data_test$carry_fwd[1]<-ifelse(data_test$taxable_income[1]<0,data_test$taxable_income[1],0)  #first year, carry-forward balance only depends on in-year taxable income
data_test$tax_payable[1]<-max(data_test$taxable_income[1],0)*tax_rate  #first year, taxable only depends on in-year taxable income
for(i in seq(2,NROW(data_test))) {
  #carry forward any further losses and/or any carried forward losses not yet offset by income
  data_test$carry_fwd[i]<-ifelse(data_test$taxable_income[i]+data_test$carry_fwd[i-1]<0,data_test$taxable_income[i]+data_test$carry_fwd[i-1],0)
  #pay taxes if the income net carried forward losses is positive
  data_test$tax_payable[i]<-max(data_test$taxable_income[i]+data_test$carry_fwd[i-1],0)*tax_rate
  }

The loop works fine, but since this is a block of code that will be replicated many times, I'd like to find a way to work this through a faster (dplyr?) script. The rest of the model code is done using tidyverse - is this perhaps a place to apply purr?

Upvotes: 1

Views: 149

Answers (1)

davsjob
davsjob

Reputation: 1950

Here is a dplyr solution :)

library(tidyverse)

tax_rate <- 0.27
data_test <- tibble(taxable_income = c(-10,-10,-10,-10,-10,20,20,20,20,20))

data_test %>% 
  mutate(cum_sum     = cumsum(taxable_income),
         carry_fwd   = if_else(cum_sum <= 0, cum_sum, 0),
         tax_payable = case_when(cum_sum  > taxable_income & cum_sum > 0     ~ taxable_income * tax_rate,
                                 cum_sum <= taxable_income & cum_sum > 0     ~ cum_sum * tax_rate,
                                 T ~ 0)) %>% 
  select(-cum_sum)

Results

# A tibble: 10 x 3
   taxable_income carry_fwd tax_payable
            <dbl>     <dbl>       <dbl>
 1            -10       -10         0  
 2            -10       -20         0  
 3            -10       -30         0  
 4            -10       -40         0  
 5            -10       -50         0  
 6             20       -30         0  
 7             20       -10         0  
 8             20         0         2.7
 9             20         0         5.4
10             20         0         5.4

Upvotes: 2

Related Questions