Funding Circle Dashboard

FC Dashboard is a shiny application that allows exploratory data analysis of the Funding Circle loanbook. It is not affiliated with Funding Circle, the untransformed loanbook data is not provided.

FC Dashboard can also be used as a personal dashboard to enable you to better understand your investments. To enable this functionality download your personal loanbook from Funding Circle and upload it using the upload option in the options menu. For the best experiance it is also recommended to upload an up to date copy of the Funding Circle loanbook (as the app combines the datasets). Data is stored temporarily during your session only; the app can also be run locally if desired (see instructions below).

Installing the shiny app locally

Manual Install

To install and run the shiny app locally on your own computer you will need to first install R, it is also suggested that you install Rstudio. After downloading the source code from this repository click on the fcdashboard.Rprof file, this will open an Rstudio window. Type the following code into the command line;

install.packages("shiny")
install.packages("shinydashboard")
install.packages("shinyBS")
install.packages("shinyWidgets")
install.packages("DT")
install.packages("tidyverse")
install.packages("rmarkdown")
install.packages('e1071')
install.packages("caret")
install.packages("ggfortify")
install.packages("plotly")
install.packages("lubridate")
install.packages("wrapr")
install.packages("stringr")

Finally save the funding circle loanbook as loanbook.csv, and your personal loanbook as personal_loanbook.csv in the fcdashboard folder. To run the app open the ui.R file and press run, depending on your computer this may take some time. Enjoy exploring the funding circle loanbook!

Using Docker

Docker is a container software that seeks to eliminate “works on my machine” issues. For installation and set up instructions see here.

This docker container is based on the shiny docker image, see here for instructions on use. To run the docker image run the following in a bash shell:

docker pull seabbs/fcdashboard
docker run --rm -p 3838:3838 seabbs/fcdashboard

The shiny server can be found on port :3838 at your local machines ip (or localhost on windows), fcdashboard can be found at your-ip:3838/fcdashboard.

Overview

Data Cleaning of FC Loanbook

Download

## Load packages
library(tidyverse)

## Clean and load fc loanbook
load_clean_loanbook <- function(loanbook_path,
                                ref_date = "date_la") {
  if (is.null(loanbook_path)) {
    ## path of loanbook 
    path  <- file.path("loanbook.csv")
  }else {
    path <- loanbook_path$datapath
  }
  
  ## Load data with miss spec as N/A
  loanbook <- read_csv(path, na = 'N/A')
  
  ## Clean loan status text
  loanbook <- loanbook %>% 
    separate(status,
             c("temp", "status"), 
             sep = ": ") %>% 
    select(-temp)
  
  ## Change variables into factors when ordering is important
  ## Make sure strings do not have free text
  loanbook <- loanbook %>% 
    mutate_at(.vars = c('status','credit_band',
                        'loan_purpose', 'sector', 
                        'business_type_name', 'region_name',
                        'whole_loan', 'repayment_type', 
                        'security_taken'),
              .funs = funs(factor))
  
  ## relevel credit band
  loanbook <- loanbook %>% 
    mutate(credit_band = credit_band %>%
             factor(levels = c('A+ (Very low risk)', 
                               'A (Low risk)', 
                               'B (Below average risk)', 
                               'C (Average risk)', 
                               'D', 
                               'E')
             ))
    
    ## Clean date of next repayment
    loanbook <- loanbook %>% 
      mutate(next_repayment = next_repayment %>% 
               replace(next_repayment %in% "", NA) %>% 
               date)
    
    ## Add repayments made
    loanbook <- loanbook %>% 
      mutate(repayments_made = term - payments_remaining) %>% 
      mutate(repayments_made = repayments_made %>% 
               factor(ordered = TRUE)
               )
  
    ## Add date of default - assuming it is date of acceptance plus number of repayments made
    loanbook <- loanbook %>% 
      mutate(date_of_default = loan_accepted_date %>% 
               replace(!status %in% "defaulted", NA)
      ) %>% 
      mutate(date_of_default = date_of_default  %m+%
               months(as.numeric(as.character(repayments_made))))
    
  ## set reference date - dropping data missing reference date
  if (ref_date %in% "date_la" || is.null(ref_date)) {
      loanbook <- loanbook %>% 
        mutate(ref_date = loan_accepted_date)
   }else if (ref_date %in% "date_d") {
      loanbook <- loanbook %>% 
        mutate(ref_date = date_of_default)
    }else if (ref_date %in% "date_np") {
      loanbook <- loanbook %>% 
        mutate(ref_date = next_repayment)
    }else if (ref_date %in% "date_fp") {
      loanbook <- loanbook %>% 
        mutate(ref_date = date_repaid)
    }
    
  loanbook <- loanbook %>% 
    filter(!is.na(ref_date))
  
  ## Change loan term to an ordinal factor
  loanbook <- loanbook %>% 
    mutate(term = term %>% factor(ordered = TRUE))
  
  ##Add variables
  loanbook <- loanbook %>% 
    mutate(grouped_loan_amount = case_when(loan_amount < 5e4 ~ "0-49,999",
                                           loan_amount < 1e5 ~ "50,000 - 99,999",
                                           loan_amount < 1.5e5 ~ "100,000 - 149,999",
                                           loan_amount < 2e5 ~ "150,000 - 199,999",
                                           loan_amount < 2.5e5 ~ "200,000 - 249,999",
                                           loan_amount < 3e5 ~ "250,000 - 299,999",
                                           loan_amount < 3.5e5 ~ "300,000 - 349,999",
                                           loan_amount < 4e5 ~ "350,000 - 399,999",
                                           loan_amount >= 4e5 ~"400,000+") %>% 
             factor(levels = c("0-49,999", "50,000 - 99,999", "100,000 - 149,999",
                               "150,000 - 199,999", "200,000 - 249,999", 
                               "250,000 - 299,999", "300,000 - 349,999",
                               "350,000 - 399,999", "400,000+"), ordered = TRUE),
           no_loans = 1, 
           loan_amount_by_facet = loan_amount,
           principal_remaining_by_facet = principal_remaining,
           principal_remaining_by_loan_amount = principal_remaining,
           principal_remaining_by_num_loans = ifelse(principal_remaining > 0, 1, 0),
           defaulted = principal_remaining %>% 
           replace(!(status %in% "defaulted"), 0),
           defaulted_by_loan_amount = defaulted,
           defaulted_by_facet = defaulted,
           defaulted_by_loan_amount = defaulted,
           defaulted_by_num_loans = ifelse(status %in% "defaulted", 1, 0),
           recoveries_by_facet = recoveries,
           recoveries_by_loan_amount = recoveries,
           recoveries_by_num_loans = ifelse(recoveries > 0, 1, 0),
           recoveries_by_defaulted = recoveries,
           unrecovered = defaulted - recoveries,
           unrecovered_by_facet = unrecovered,
           unrecovered_by_loan_amount = unrecovered,
           unrecovered_by_num_loans = ifelse(unrecovered > 0, 1, 0),
           unrecovered_by_defaulted = unrecovered,
           day = lubridate::day(ref_date) %>%  factor,
           day_of_week = lubridate::wday(ref_date, label = TRUE),
           week = lubridate::week(ref_date) %>% factor,
           month = lubridate::month(ref_date, label = TRUE),
           year = lubridate::year(ref_date) %>% factor
           )
  return(loanbook)
  
}

Utility Functions

Download

#' Load packages
library(tidyverse)
library(plotly)
library(lubridate)
library(wrapr)


#' Summary statistics
summary_stats <- function(df) { 
  df %>% 
    summarise(amount_lent = sum(loan_amount, na.rm = TRUE),
              principal_repaid = sum(loan_amount - principal_remaining, na.rm = TRUE),
              recoveries = sum(recoveries, na.rm = TRUE),
              defaulted = principal_remaining %>%
                replace(!status %in% "defaulted", NA) %>% 
                sum(na.rm = TRUE)
    ) 
}


## Summarise data
summarise_loanbook <- function(df = NULL,
                               xvar = NULL,
                               yvar = NULL, 
                               strat = NULL, 
                               facet = NULL) {
  
  ## Set up filtering
  strat_vect  <- strat
  if (!is.null(xvar)) {
    strat_vect <- c(strat_vect, xvar)
  }
  if (!facet %in% "no_facet") {
    strat_vect <- c(strat_vect, facet)
  }
  
  ##Group loanbook for summary
  group_df <- group_by(df, .dots = strat_vect)
  
  if (str_detect(yvar, "by_loan_amount")) {
    ##Summarise, normalising by loan amount in each group
    group_df <- group_df %>% 
      summarise_at(.vars = yvar,
                   .funs = funs(100 * sum(.)/sum(loan_amount)) 
      ) %>% 
      mutate_at(.vars = yvar, .funs = funs(round(., digits = 1)))
    
  }else if (str_detect(yvar, "by_defaulted")) {
    group_df <- group_df %>% 
      summarise_at(.vars = yvar,
                   .funs = funs(100 * sum(.)/sum(defaulted)) 
      ) %>% 
      mutate_at(.vars = yvar, .funs = funs(round(., digits = 1)))
    
  }else if (str_detect(yvar, "by_facet")) {
    ##Summarise, normalising by within facet total
    if (facet %in% "no_facet" && is.null(xvar)) {
        total_facet <- sum(df[[yvar]], na.rm = TRUE)
        
        group_df <- summarise_at(group_df, .vars = yvar,
                                 .funs = funs(100 * sum(.)/total_facet) 
        )
    }else{

      if (!is.null(xvar) && !facet %in% "no_facet") {
        facet_vect <- c(facet, xvar)
      }else if (is.null(xvar) && !facet %in% "no_facet") {
        facet_vect <- facet
      }else if (!is.null(xvar) && facet %in% "no_facet") {
        facet_vect <- xvar
      }
      
      total_facet <- df %>% 
        group_by(.dots = facet_vect) %>% 
        summarise_at(.vars = yvar, .funs = funs(sum(.))) %>% 
        ungroup %>% 
        rename_at(.vars =  yvar, .funs = (function(.) {"facet_sum"}))
      
      group_df <- group_df %>% 
        full_join(total_facet) %>% 
        ungroup %>% 
        group_by(.dots = strat_vect) %>% 
        summarise_at(.vars = yvar,
                     .funs = funs(100 * sum(., na.rm = TRUE)/facet_sum[1]) 
        )
    }
    
    group_df <- mutate_at(group_df, 
                          .vars = yvar, 
                          .funs = funs(round(., digits = 1)))
    
  }else if (str_detect(yvar, "no_loans")) {
    group_df <- summarise_at(group_df,
                             .vars = yvar,
                             .funs = funs(length(.)))
    }else if (str_detect(yvar, "by_num_loans")) {
      ##Summarise, normalising by loan amount in each group
      group_df <- group_df %>% 
        summarise_at(.vars = yvar,
                     .funs = funs(100 * sum(.)/sum(no_loans)) 
        ) %>% 
        mutate_at(.vars = yvar, .funs = funs(round(., digits = 1)))
      }else{
    group_df <- group_df %>% 
      summarise_at(.vars = yvar, 
                   .funs = funs(sum(.)) 
      ) %>% 
      mutate_at(.vars = yvar, 
                .funs = funs(round(./1e6, digits = 1)))
  }
  
  ##Remove missing variables
  group_df <- na.omit(group_df)
  return(group_df)
}

##Plot loan book summary
plot_loanbook_summary <- function(df, 
                                  yvar, 
                                  strat,
                                  facet,
                                  scaled_to_mil = FALSE,
                                  plotly = TRUE) {
  
  if (facet %in% "no_facet") {
    size_point <- 7
  }else {
    size_point <- 2
  }
  
  p <- df %>%
    ggplot(aes_string(x = strat, y = yvar, colour = strat)) + 
    geom_segment(aes_string(xend = strat, yend = 0)) + 
    geom_point(size = size_point)
  
  if (facet %in% "no_facet") {
    p <- p +
      geom_text(aes_string(label = yvar, y = yvar),
                vjust = 0, size = 2, colour = "white")
  }
  
  if (scaled_to_mil) {
    if (str_detect(yvar, "by_loan_amount") | 
        str_detect(yvar, "by_facet") |
        str_detect(yvar, "by_defaulted") |
        str_detect(yvar, "by_num_loans")) {
      p <- p + ylab(paste0(yvar, " (%)"))
    }else if (str_detect(yvar, "no_loans")) {
      p <- p + ylab(paste0(yvar, " (no.)"))
      }else {
      p <- p +
        ylab(paste0(yvar, " (£, Millions)"))
    }
  }
  
  p <- p +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45,hjust = 1),
          legend.position = "none")
  
  if (!facet %in% "no_facet") {
    p <- p +
      facet_wrap(facet, scales = "fixed")
  }

  
    
  if (plotly) {
    ggplotly(p)
  }else{
    p
  }
}


#' Plot amount lent
plot_by_date <- function(df, 
                         by = "loan_amount", 
                         strat = "credit_band",
                         facet = "no_facet",
                         plotly = TRUE,
                         round_date = "month") {
  
      df <- df %>% 
        mutate(Date = 
                 lubridate::floor_date(ref_date, unit = round_date))
      
      df <- df %>%
        summarise_loanbook(xvar = "Date",
                           yvar = by, 
                           strat = strat, 
                           facet = facet)
      
      p <- df %>% 
        ggplot(aes_string(x = "Date",
                   y = by, 
                   colour = strat)) +
        geom_point() +
        geom_line() +
        theme_minimal() +
        theme(legend.position = "bottom")
      
      if (str_detect(by, "by_loan_amount") || 
          str_detect(by, "by_facet") || 
          str_detect(by, "by_defaulted") ||
          str_detect(by, "by_num_loans")) {
        p <- p + ylab(paste0(by, " (%)")) 
      }else if (str_detect(by, "no_loans")) {
        p <- p + ylab(paste0(by, " (no.)"))
        }else {
        p <- p + ylab(paste0(by, " (£, Millions)"))
      }
      
      if (!facet %in% "no_facet") {
        p <- p + facet_wrap(facet, scales = "fixed")
      }

  if (plotly) {
    ggplotly(p) %>%
      plotly::layout(autosize = TRUE)
  }else {
    p
  }
}

#' violin plot of data
plot_dist <- function(df, 
                      by = "loan_amount",
                      strat = "credit_band",
                      facet = "no_facet",
                      plotly = TRUE)
  wrapr::let(
    list(X = by, Y = strat), {
      if (str_detect(by, "by_loan_amount")) {
        df <- df %>% 
          mutate(X = 100 * X / loan_amount)
      }else if (str_detect(by, "by_defaulted")) {
        df <- df %>% 
          mutate(X = 100 * X / defaulted)
      }else {
        df <- df %>% 
          mutate(X = X / 1e3)
      }

      p <- df %>% 
        ggplot(aes(x = Y, y = X, fill = Y)) +
        geom_violin(draw_quantiles = c(0.25, 0.5, 0.75)) +
        theme_minimal() +
        theme(axis.text.x = element_text(angle = 45,hjust = 1),
              legend.position = "none")
      
      if (str_detect(by, "by_loan_amount") | str_detect(by, "by_defaulted")) {
        p <- p +  ylab(paste0(by, " (%)"))
      }else{
       p <- p + ylab(paste0(by, " (£, Thousands)")) 
      }
      
      if (!facet %in% "no_facet") {
        p <- p + facet_wrap(facet, scales = "fixed")
      }
      
      if (!by %in% c("no_loans") && !str_detect(by, "by_facet") && !str_detect(by, "by_num_loans")) {
        if (plotly) {
          ggplotly(p) %>%
            plotly::layout(autosize = TRUE)
        }else {
          p
        }
      }
    }
  )

#' scatter of 2 numeric variables
plot_scatter <- function(df, 
                         by = "loan_amount",
                         also_by = "term",
                         strat = "credit_band",
                         facet = "no_facet",
                         plotly = TRUE,
                         alpha = 0.4) {
  if (also_by %in% "term") {
    df <- df %>% 
      mutate(term = term %>% 
               as.character %>% 
               as.numeric)
  }
  
  wrapr::let(
    list(X = by, Y = strat, Z = also_by), {
      
   if (str_detect(by, "by_loan_amount")) {
     df <- df %>% 
       mutate(X = 100 * X / loan_amount)
   }else if (str_detect(by, "by_defaulted")) {
     df <- df %>% 
       mutate(X = 100 * X / defaulted)
   }else{
     df <- df %>%
       mutate(X = X/1e3)
   }

      p <- df %>% 
        ggplot(aes(x = X, y = Z, colour = Y)) +
        geom_count(alpha = alpha, show.legend = TRUE) +
        theme_minimal()
      
      if (str_detect(by, "by_loan_amount") | str_detect(by, "by_defaulted")) {
        p <- p + xlab(paste0(by, " (%)"))
      }else {
        p <- p + xlab(paste0(by, " (£, Thousands)"))
      }
      
      if (!facet %in% "no_facet") {
        p <- p + facet_wrap(facet, scales = "fixed")
      }
      
      if (!by %in% c("no_loans") && !str_detect(by, "by_facet") && !str_detect(by, "by_num_loans")) {
        if (plotly) {
          ggplotly(p) %>%
            plotly::layout(autosize = TRUE)
        }else {
          p
        }
      }
    }
  )
  
}


pca_on_loanbook <- function(df, no_pca = 2) {
  #' Perform pca using caret
  #' Drop variables with missing information/not true numeric variables
  filter_loanbook <-  df %>% 
    mutate(term = term %>% as.character %>% as.numeric) %>% 
    select(-id, 
           -next_repayment, 
           -year_incorporated, 
           -loan_guaranteed,
           -max_accepted_bid_rate,
           -min_accepted_bid_rate)
  
  numeric_loanbook <- filter_loanbook %>% 
    select_if(.predicate = is.numeric) %>% 
    as.data.frame
  
  process_loanbook <- numeric_loanbook %>% 
    preProcess(method = c("BoxCox", "center", "scale"))
  
  process_loanbook <- predict(process_loanbook, numeric_loanbook)
  
  pca_loanbook <- prcomp(process_loanbook, 
                         center = FALSE,
                         scale. = FALSE,
                         rank. = no_pca)
  return(list(pca_loanbook, filter_loanbook)) 
}

plot_pca <- function(df_list,
                     pc_1 = 1, 
                     pc_2 = 2,
                     strat, 
                     plotly = TRUE,
                     alpha = 0.2) {
  p <- autoplot(df_list[[1]], 
                x = pc_1,
                y = pc_2, 
                data = df_list[[2]],
                colour = strat,
                alpha = alpha,
                loadings = TRUE,
                loadings.colour = "black",
                loadings.label = TRUE,
                loadings.label.colour = "black",
                loadings.label.size = 3) + 
    theme_minimal()
  
  if (plotly) {
    ggplotly(p)
  }else{
    p
  }
}

#' Convert million
convert_million <- function(x, label = "M") {
  x <- round(x / 1e6, 1) 
  x <- format(x, big.mark = ",")
  x <- paste0(x, label)
}

#' Return with per
return_with_per <- function(df, num, denom) {
  num <- enquo(num)
  denom <- enquo(denom)
  
  paste0(df %>% 
           select(!!num) %>% 
           convert_million, " (", 
         df %>%
           mutate(per = (!!num) / (!!denom)) %>% 
           mutate(per = round(per * 100, digits = 1)) %>% 
           select(per), "%)")
}

Personal Loanbook Functions

Download

library(tidyverse)
library(wrapr)
library(stringr)

#' - Third tab: - 
#'   - Comparing personal loanbook and fc loan book
#'   - For comparisions need to use proportions or will not be comparable - reuse graphs but with proportions if possible
#'   - Sub tab PCA your data set main dataset
#'   - Bad debt interest by number of loans and sample from loanbook, add option to sample based on your distribution

## Load and clean personal loanbook
loan_clean_personal_loanbook <- function(personal_loanbook_path) {
  
  if (is.null(personal_loanbook_path)) {
    if (file.exists("personal_loanbook.csv")) {
      path <- "personal_loanbook.csv"
    }else {
      path <- NULL
    }
  }else {
    path <- personal_loanbook_path$datapath
  }
  
  personal_loanbook <- read_csv(path)
  
  ##Change risk to ordered factor
  personal_loanbook <- personal_loanbook %>% 
    mutate(Risk = Risk %>% factor(
      levels = c("A+", "A", "B", "C", "D", "E")
    ))
  
  ##Munge and reformat rate so that it is ordered
  personal_loanbook <- personal_loanbook %>%
    mutate(Rate = str_replace_all(Rate, "%", "") %>% 
             as.numeric) %>% 
    mutate(Rate = Rate %>% 
             factor(levels = unique(Rate)[order(unique(Rate))],
                    ordered = TRUE)
           ) 
  return(personal_loanbook)
}

## Join FC and Personal Loanbooks
bind_loanbooks <- function(personal_loanbook, fc_loanbook, verbose= TRUE) {
  personal_loanbook <- personal_loanbook %>% 
  rename(id = `Loan ID`) %>%
    mutate(invested_in = "Yes")
combined_loanbook <- fc_loanbook %>% 
  full_join(personal_loanbook) %>% 
  mutate(invested_in = invested_in %>% 
           replace(is.na(invested_in), "No")) %>% 
  mutate(`Repayments made` = as.numeric(as.character(term)) - payments_remaining %>% 
           as.integer) %>% 
  mutate(`Percentage repaid` = round(`Repayments made` / as.numeric(as.character(term)) * 100))

if (verbose) {
  loans_without_data <- is.na(combined_loanbook$credit_band) %>% sum
  message("Loan books are bound with ", loans_without_data, " missing loan entries.")
  if (loans_without_data > 1) {
    message("Consider uploading an updated funding circle loan book as some of your loans are missing data")
  }
}
return(combined_loanbook)
}
## Overall summary stats for boxes
p_loanbook_overall_sum_info <- function(df,
                                        aplus_bad = 0.6,
                                        a_bad = 1.5, 
                                        b_bad = 2.3,
                                        c_bad = 3.3,
                                        d_bad = 5,
                                        e_bad = 8) {
  ##Transform rate for  calc
  df <- df %>%
    mutate(rate_prog = Rate %>% 
             str_split(pattern = "%") %>%
             map_chr(paste, collapse = "") %>% 
             as.numeric) %>% 
    mutate(bad_debt = case_when(Risk %in% "A+" ~ aplus_bad,
                                Risk %in% "A" ~ a_bad,
                                Risk %in% "B" ~ b_bad,
                                Risk %in% "C" ~ c_bad,
                                Risk %in% "D" ~ d_bad,
                                Risk %in% "E" ~ e_bad)) %>% 
    mutate(anul_adj_rate = 100 * (1 + (rate_prog - bad_debt - 1) / (100 * 12)) ^ 12 - 100) %>% 
    mutate(anul_rate_prog = 100 * (1 + rate_prog / (100 * 12)) ^ 12 - 100) %>% 
    mutate(rate_weight = `Principal remaining` / sum(`Principal remaining`))
  
  ##Summarise on sector
  sector_max <- df %>% 
    group_by(Sector) %>% 
    summarise(prin_remaining = sum(`Principal remaining`)) %>% 
    ungroup %>%
    pull(prin_remaining) %>% 
    max
  
  ## Total lent
  total_lent <- df$`Principal remaining` %>% sum

  ## Build table
  df %>% 
    mutate(crude_interest = anul_rate_prog * `Principal remaining`) %>% 
    mutate(adj_interest = anul_adj_rate * `Principal remaining`) %>% 
    summarise(
      `Amount lent` = sum(`Principal remaining`) %>% 
        paste0("£", .),
      `Amount late (%)` = `Principal remaining` %>%
        replace(!`Loan status` %in% "Late", 0) %>% 
        sum,
      `Amount defaulted (%)` = `Principal remaining` %>%
        replace(!`Loan status` %in% c("Defaulted", "Bad debt", "Bad Debt"), 0) %>% 
        sum,
      `Number of loans invested in` = n(),
      `Number of loan parts` = sum(`Number of loan parts`),
      `Maximum lent in a single loan (%)` = max(`Principal remaining`),
      `Maximum lent to a single sector (%)` = sector_max,
      `Crude interest rate` = sum(anul_rate_prog * rate_weight) %>% 
        round(digits = 1) %>% 
        paste0("%"),
      `Adjusted interest rate*` = sum(anul_adj_rate * rate_weight) %>% 
        round(digits = 1) %>% 
        paste0("%")
      ) %>% 
    mutate_at(.vars = c("Amount late (%)",
                        "Amount defaulted (%)",
                        "Maximum lent in a single loan (%)",
                        "Maximum lent to a single sector (%)"),
              .funs = funs(paste0("£", ., " (", 
                                  round(. / total_lent * 100, digits = 1),
                                  "%)")))
}
## Summary table stratified by stratification variable
p_loanbook_sum_table <- function(df, strat) {
  ## Total amount lent
  total_amount_lent <- sum(df$`Principal remaining`)
  
  ##Summarise loanbook
  df_sum <- df %>% 
    group_by(.dots = strat) %>% 
    summarise(`Amount lent (£)` = sum(`Principal remaining`),
              `Number of loan parts` = sum(`Number of loan parts`),
              `Percentage of loanbook (%)` = round(`Amount lent (£)` / total_amount_lent * 100, digits = 1)
        ) %>% 
    mutate(`Amount lent (£)` = round(`Amount lent (£)`, digits = 0))

  return(df_sum)
}

UI

Download

## Load packages
library(shiny)
library(shinydashboard)
library(shinyBS)
library(shinyWidgets)
library(DT)
library(tidyverse)
library(rmarkdown)
library(caret)
library(ggfortify)
library(plotly)
library(lubridate)
library(wrapr)
library(stringr)

## Source cleaned data
source("clean_fc_loanbook.R")

## Source utility functions
source("utility_functions.R")

## Source functions for personal loanbook
source("personal_loanbook.R")

## Slider in menu bar to control dates of data shown
## Buttons showing summary data at bottom
## two summary graphs in main dashboard

sidebar <- dashboardSidebar(
  hr(),
  sidebarMenu(id = "menu",
              menuItem("Personal Dashboard", icon = icon("dashboard"),
                       menuSubItem("Dashboard", tabName = "p_dashboard", icon = icon("dashboard")),
                       menuSubItem("Exploratory Plots", tabName = "p_exploratory", icon = icon("line-chart")),
                       menuSubItem("PCA", tabName = "p_pca", icon = icon("line-chart"))
              ),
              menuItem("FC Dashboard", icon = icon("dashboard"),
                       menuSubItem("Dashboard", tabName = "fc_dashboard", icon = icon("dashboard")),
                       menuSubItem("PCA", tabName = "fc_pca", icon = icon("line-chart"))
                       ),
              menuItem("About", tabName = "readme", icon = icon("info"), selected = TRUE),
              menuItem("Code",  icon = icon("code"),
                       menuSubItem("Github", href = "https://github.com/seabbs/fcdashboard", icon = icon("github")),
                       menuSubItem("clean_fc_loanbook.R", tabName = "dataclean", icon = icon("angle-right")),
                       menuSubItem("utility_functions.R", tabName = "utility_functions", icon = icon("angle-right")),
                       menuSubItem("personal_loanbook.R", tabName = "personal_loanbook", icon = icon("angle-right")),
                       menuSubItem("ui.R", tabName = "ui", icon = icon("angle-right")),
                       menuSubItem("server.R", tabName = "server", icon = icon("angle-right"))
              )
  ),
  hr(),
  tipify(uiOutput("date_slider"),
         title = "Select the data range. Data out of date? Tweet @seabbs."),
  checkboxInput('set_ref_date',
                "Set reference date",
                value = FALSE),
  conditionalPanel(condition = 'input.set_ref_date',
                   selectInput("ref_date",
                               "Reference date:",
                               list(`Date of loan acceptance` = "date_la",
                                    `Date of default` = "date_d",
                                    `Date of next payment` = "date_np",
                                    `Date of repayment` = "date_fp"))
  ),
  conditionalPanel(condition = 'input.menu == "readme"',
                   fileInput("loanbook", 
                             "Upload FC loanbook",
                             accept = c(
                               "text/csv",
                               "text/comma-seperated-values,text/plain",
                               ".csv")
                   ),
                   fileInput("personal_loanbook", 
                             "Upload personal loanbook",
                             accept = c(
                               "text/csv",
                               "text/comma-seperated-values,text/plain",
                               ".csv")
                   )),
  conditionalPanel(condition = 'input.menu == "fc_dashboard"',
selectInput("fc_yaxis", 
                               "Variable to summarise:",
                               list(`Number of loans` = "no_loans",
                                    `Loan amount` = "loan_amount",
                                    `Loan amount (%)` = "loan_amount_by_facet",
                                    `Principal remaining` = "principal_remaining",
                                    `Principal remaining (%)` = "principal_remaining_by_facet",
                                    `Principal remaining/Loan amount` = "principal_remaining_by_loan_amount",
                                    `Principal remaining/No. of loans` = "principal_remaining_by_num_loans",
                                     Defaulted = "defaulted",
                                    `Defaulted (%)` = "defaulted_by_facet",
                                    `Defaulted/Loan amount` = "defaulted_by_loan_amount",
                                    `Defaulted/No. of loans` = "defaulted_by_num_loans",
                                     Recoveries = "recoveries",
                                    `Recoveries (%)` = "recoveries_by_facet",
                                    `Recoveries/Loan amount` = "recoveries_by_loan_amount",
                                    `Recoveries/No. of loans` = "recoveries_by_num_loans",
                                    `Recoveries/Defaulted` = "recoveries_by_defaulted",
                                     Unrecovered = "unrecovered",
                                    `Unrecovered (%)` = "unrecovered_by_facet",
                                    `Unrecovered/Loan amount` = "unrecovered_by_loan_amount",
                                    `Unrecovered/No. of loans` = "unrecovered_by_num_loans",
                                    `Unrecovered/Defaulted` = "unrecovered_by_defaulted"
                               ),
            selected =  "loan_amount"
                   ),
                   selectInput("fc_strat_var", 
                               "Variable to stratify by:",
                               list(`Credit band` = 
                                      "credit_band",
                                    Status = 
                                      "status",
                                    `Loan purpose` = 
                                      "loan_purpose",
                                    Sector = "sector",
                                    Region = "region_name",
                                    `Loan term` = "term",
                                    `Loan amount` = "grouped_loan_amount",
                                    `Repayments made` = "repayments_made",
                                    `Whole loan` = "whole_loan",
                                    `Repayment type` = "repayment_type",
                                    `Security taken` = "security_taken",
                                     Day = "day",
                                    `Day of week` = "day_of_week",
                                     Week = "week", 
                                     Month = "month",
                                     Year = "year"
                               )
                               
                   ),
                    selectInput("fc_facet_var", 
                                "Variable to facet by:",
                                list(`-` = "no_facet",
                                     `Credit band` = 
                                       "credit_band",
                                     Status = 
                                       "status",
                                     `Loan purpose` = 
                                       "loan_purpose",
                                     Sector = "sector",
                                     Region = "region_name",
                                     `Loan term` = "term",
                                     `Loan amount` = "grouped_loan_amount",
                                     `Repayments made` = "repayments_made",
                                     `Whole loan` = "whole_loan",
                                     `Repayment type` = "repayment_type",
                                     `Security taken` = "security_taken",
                                     Day = "day",
                                     `Day of week` = "day_of_week",
                                     Week = "week", 
                                     Month = "month",
                                     Year = "year"
                                )
                                
                  ),
                  selectInput("fc_dash_filter", 
                  "Variable to filter by:",
                  list(`-` = "no_filter",
                       `Credit band` = 
                       "credit_band",
                      Status = 
                       "status",
                       `Loan purpose` = 
                       "loan_purpose",
                       Sector = "sector",
                       Region = "region_name",
                       `Loan term` = "term",
                       `Loan amount` = "grouped_loan_amount",
                       `Repayments made` = "repayments_made",
                       `Whole loan` = "whole_loan",
                       `Repayment type` = "repayment_type",
                       `Security taken` = "security_taken",
                      Day = "day",
                      `Day of week` = "day_of_week",
                      Week = "week", 
                      Month = "month",
                      Year = "year"
                    )),
                  conditionalPanel(condition = "input.fc_dash_filter != 'no_filter'",
                                   uiOutput("filter_var_picker_fc_dash")
                  ),
                  conditionalPanel(condition = "input.fc_dash_filter != 'no_filter'",
                                  selectInput("fc_dash_filter_2", 
                                              "Second variable to filter by:",
                                              list(`-` = "no_filter",
                                                   `Credit band` = 
                                                     "credit_band",
                                                   Status = 
                                                     "status",
                                                   `Loan purpose` = 
                                                     "loan_purpose",
                                                   Sector = "sector",
                                                   Region = "region_name",
                                                   `Loan term` = "term",
                                                   `Loan amount` = "grouped_loan_amount",
                                                   `Repayments made` = "repayments_made",
                                                   `Whole loan` = "whole_loan",
                                                   `Repayment type` = "repayment_type",
                                                   `Security taken` = "security_taken",
                                                   Day = "day",
                                                   `Day of week` = "day_of_week",
                                                   Week = "week", 
                                                   Month = "month",
                                                   Year = "year"
                                              )),
                                  conditionalPanel(condition = "input.fc_dash_filter_2 != 'no_filter'",
                                                   uiOutput("filter_var_picker_fc_dash_2")
                                  ))
),
conditionalPanel(condition = 'input.menu == "p_exploratory"',
                 selectInput("p_yaxis", 
                             "Variable to summarise:",
                             list(`Number of loans` = "no_loans",
                                  `Loan amount` = "loan_amount",
                                  `Loan amount (%)` = "loan_amount_by_facet",
                                  `Principal remaining` = "principal_remaining",
                                  `Principal remaining (%)` = "principal_remaining_by_facet",
                                  `Principal remaining/Loan amount` = "principal_remaining_by_loan_amount",
                                  `Principal remaining/No. of loans` = "principal_remaining_by_num_loans",
                                  Defaulted = "defaulted",
                                  `Defaulted (%)` = "defaulted_by_facet",
                                  `Defaulted/Loan amount` = "defaulted_by_loan_amount",
                                  `Defaulted/No. of loans` = "defaulted_by_num_loans",
                                  Recoveries = "recoveries",
                                  `Recoveries (%)` = "recoveries_by_facet",
                                  `Recoveries/Loan amount` = "recoveries_by_loan_amount",
                                  `Recoveries/No. of loans` = "recoveries_by_num_loans",
                                  `Recoveries/Defaulted` = "recoveries_by_defaulted",
                                  Unrecovered = "unrecovered",
                                  `Unrecovered (%)` = "unrecovered_by_facet",
                                  `Unrecovered/Loan amount` = "unrecovered_by_loan_amount",
                                  `Unrecovered/No. of loans` = "unrecovered_by_num_loans",
                                  `Unrecovered/Defaulted` = "unrecovered_by_defaulted"
                             ),
                             selected =  "loan_amount"
                 ),
                 selectInput("p_strat_var", 
                             "Variable to stratify by:",
                             list(`Credit band` = 
                                    "credit_band",
                                  Status = 
                                    "status",
                                  `Loan purpose` = 
                                    "loan_purpose",
                                  Sector = "sector",
                                  Region = "region_name",
                                  `Loan term` = "term",
                                  `Loan amount` = "grouped_loan_amount",
                                  `Repayments made` = "repayments_made",
                                  `Whole loan` = "whole_loan",
                                  `Repayment type` = "repayment_type",
                                  `Security taken` = "security_taken",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             )
                             
                 ),
                 selectInput("p_facet_var", 
                             "Variable to facet by:",
                             list(`-` = "no_facet",
                                  `Credit band` = 
                                    "credit_band",
                                  Status = 
                                    "status",
                                  `Loan purpose` = 
                                    "loan_purpose",
                                  Sector = "sector",
                                  Region = "region_name",
                                  `Loan term` = "term",
                                  `Loan amount` = "grouped_loan_amount",
                                  `Repayments made` = "repayments_made",
                                  `Whole loan` = "whole_loan",
                                  `Repayment type` = "repayment_type",
                                  `Security taken` = "security_taken",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             )
                             
                 ),
                 selectInput("p_exp_filter", 
                                 "Variable to filter by:",
                             list(`-` = "no_filter",
                                  `Credit band` = 
                                    "credit_band",
                                  Status = 
                                    "status",
                                  `Loan purpose` = 
                                    "loan_purpose",
                                  Sector = "sector",
                                  Region = "region_name",
                                  `Loan term` = "term",
                                  `Loan amount` = "grouped_loan_amount",
                                  `Repayments made` = "repayments_made",
                                  `Whole loan` = "whole_loan",
                                  `Repayment type` = "repayment_type",
                                  `Security taken` = "security_taken",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             )),
                 conditionalPanel(condition = "input.p_exp_filter != 'no_filter'",
                                  uiOutput("filter_var_picker_p_exp")
                 ),
                 conditionalPanel(condition = "input.p_exp_filter != 'no_filter'",
                                   selectInput("p_exp_filter_2", 
                                               "Second variable to filter by:",
                                               list(`-` = "no_filter",
                                                    `Credit band` = 
                                                      "credit_band",
                                                    Status = 
                                                      "status",
                                                    `Loan purpose` = 
                                                      "loan_purpose",
                                                    Sector = "sector",
                                                    Region = "region_name",
                                                    `Loan term` = "term",
                                                    `Loan amount` = "grouped_loan_amount",
                                                    `Repayments made` = "repayments_made",
                                                    `Whole loan` = "whole_loan",
                                                    `Repayment type` = "repayment_type",
                                                    `Security taken` = "security_taken",
                                                    Day = "day",
                                                    `Day of week` = "day_of_week",
                                                    Week = "week", 
                                                    Month = "month",
                                                    Year = "year"
                                               )),
                                   conditionalPanel(condition = "input.p_exp_filter_2 != 'no_filter'",
                                                    uiOutput("filter_var_picker_p_exp_2")
                                   )),
                 checkboxInput('p_exp_filter_repaid',
                               "Filter repaid loans",
                               value = TRUE)
),
conditionalPanel(condition = 'input.menu == "fc_pca"',
                 sliderInput(inputId = "fc_no_pca", 
                             label = "Number of Principal components:",
                             min = 0,
                             max = 10,
                             value = 2),
                 sliderInput(inputId = "fc_pca_1", 
                             label = "First component to plot:",
                             min = 0,
                             max = 10,
                             value = 1),
                 sliderInput(inputId = "fc_pca_2", 
                             label = "Second component to plot:",
                             min = 0,
                             max = 10,
                             value = 2),
                 selectInput("fc_strat_var2", 
                             "Variable to stratify by:",
                             list(`Credit band` = 
                                    "credit_band",
                                  Status = 
                                    "status",
                                  `Loan purpose` = 
                                    "loan_purpose",
                                  Sector = "sector",
                                  Region = "region_name",
                                  `Loan term` = "term",
                                  `Loan amount` = "grouped_loan_amount",
                                  `Repayments made` = "repayments_made",
                                  `Whole loan` = "whole_loan",
                                  `Repayment type` = "repayment_type",
                                  `Security taken` = "security_taken",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             ))),

conditionalPanel(condition = 'input.menu == "p_pca"',
                 sliderInput(inputId = "p_no_pca", 
                             label = "Number of Principal components:",
                             min = 0,
                             max = 10,
                             value = 2),
                 sliderInput(inputId = "p_pca_1", 
                             label = "First component to plot:",
                             min = 0,
                             max = 10,
                             value = 1),
                 sliderInput(inputId = "p_pca_2", 
                             label = "Second component to plot:",
                             min = 0,
                             max = 10,
                             value = 2),
                 selectInput("p_strat_var2", 
                             "Variable to stratify by:",
                             list(`Credit band` = 
                                    "credit_band",
                                  Status = 
                                    "status",
                                  `Loan purpose` = 
                                    "loan_purpose",
                                  Sector = "sector",
                                  Region = "region_name",
                                  `Loan term` = "term",
                                  `Loan amount` = "grouped_loan_amount",
                                  `Repayments made` = "repayments_made",
                                  `Whole loan` = "whole_loan",
                                  `Repayment type` = "repayment_type",
                                  `Security taken` = "security_taken",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             ))),
conditionalPanel(condition = 'input.menu == "p_dashboard"',
                 selectInput("p_dash_strat", 
                             "Variable to stratify by:",
                             list(Risk = 
                                    "Risk",
                                  Rate = "Rate",
                                  `Loan purpose` = 
                                    "`Loan purpose`",
                                  Sector = "`Sector`",
                                  `Next payment date` = 
                                    "`Next payment date`",
                                  `Loan status` = "`Loan status`",
                                  Region = "Region",
                                  `Loan term` = "`Loan term`",
                                  `Loan amount` = "`Grouped loan amount`",
                                  `Repayments made` = "`Repayments made`",
                                  `Repayments left` = "`Repayments left`",
                                  `Percentage repaid` = "`Percentage repaid`",
                                  `Repayment type` = "`Repayment type`",
                                  `Security taken` = "`Security taken`",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             )),
                 selectInput("p_dash_facet", 
                             "Variable to facet by:",
                             list(`-` = "no_facet",
                                  Risk = 
                                    "Risk",
                                  Rate = "Rate",
                                  `Loan purpose` = 
                                    "`Loan purpose`",
                                  Sector = "`Sector`",
                                  `Next payment date` = 
                                    "`Next payment date`",
                                  `Loan status` = "`Loan status`",
                                  Region = "Region",
                                  `Loan term` = "`Loan term`",
                                  `Loan amount` = "`Grouped loan amount`",
                                  `Repayments made` = "`Repayments made`",
                                  `Repayments left` = "`Repayments left`",
                                  `Percentage repaid` = "`Percentage repaid`",
                                  `Repayment type` = "`Repayment type`",
                                  `Security taken` = "`Security taken`",
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             )),
                 selectInput("p_dash_filter", 
                             "Variable to filter by:",
                             list(`-` = "no_filter",
                                  Risk = 
                                    "Risk",
                                  Rate = "Rate",
                                  `Loan purpose` = 
                                    "Loan purpose",
                                  Sector = "Sector",
                                  `Next payment date` = 
                                    "Next payment date",
                                  `Loan status` = "Loan status",
                                  Region = "Region",
                                  `Loan term` = "Loan term",
                                  `Loan amount` = "Grouped loan amount",
                                  `Repayments made` = "Repayments made",
                                  `Repayments left` = "Repayments left",
                                  `Percentage repaid` = "Percentage repaid",
                                  `Repayment type` = "Repayment type",
                                  `Security taken` = "Security taken", 
                                  Day = "day",
                                  `Day of week` = "day_of_week",
                                  Week = "week", 
                                  Month = "month",
                                  Year = "year"
                             )),
                 conditionalPanel(condition = "input.p_dash_filter != 'no_filter'",
                                  uiOutput("filter_var_picker")
                 ),
                 conditionalPanel(condition = "input.p_dash_filter != 'no_filter'",
                                  selectInput("p_dash_filter_2", 
                                              "Second variable to filter by:",
                                              list(`-` = "no_filter",
                                                   Risk = 
                                                     "Risk",
                                                   Rate = "Rate",
                                                   `Loan purpose` = 
                                                     "Loan purpose",
                                                   Sector = "Sector",
                                                   `Next payment date` = 
                                                     "Next payment date",
                                                   `Loan status` = "Loan status",
                                                   Region = "Region",
                                                   `Loan term` = "Loan term",
                                                   `Loan amount` = "Grouped loan amount",
                                                   `Repayments made` = "Repayments made",
                                                   `Repayments left` = "Repayments left",
                                                   `Percentage repaid` = "Percentage repaid",
                                                   `Repayment type` = "Repayment type",
                                                   `Security taken` = "Security taken",
                                                   Day = "day",
                                                   `Day of week` = "day_of_week",
                                                   Week = "week", 
                                                   Month = "month",
                                                   Year = "year"
                                              )),
                                  conditionalPanel(condition = "input.p_dash_filter_2 != 'no_filter'",
                                                   uiOutput("filter_var_picker_2")
                                  )),
                 checkboxInput("show_bad_debt_opts",
                               "Edit bad debt estimates:",
                               value = FALSE),
                 conditionalPanel(condition = "input.show_bad_debt_opts",
                                        numericInput(inputId = "aplus_bad", 
                                                       label = "A+: Percentage bad debt",
                                                       min = 0,
                                                       max = 100,
                                                       value = 0.6,
                                                       step = 0.1
                                          ),
                                          numericInput(inputId = "a_bad", 
                                                       label = "A: Percentage bad debt",
                                                        min = 0,
                                                        max = 100,
                                                        value = 1.5,
                                                        step = 0.1),
                                           numericInput(inputId = "b_bad", 
                                                        label = "B: Percentage bad debt",
                                                        min = 0,
                                                        max = 100,
                                                        value = 2.3,
                                                        step = 0.1),
                                            numericInput(inputId = "c_bad", 
                                                         label = "C: Percentage bad debt",
                                                         min = 0,
                                                         max = 100,
                                                         value = 3.3,
                                                         step = 0.1),
                                            numericInput(inputId = "d_bad", 
                                                         label = "D: Percentage bad debt",
                                                         min = 0,
                                                         max = 100,
                                                         value = 5,
                                                         step = 0.1),
                                            numericInput(inputId = "e_bad", 
                                                         label = "E: Percentage bad debt",
                                                         min = 0,
                                                         max = 100,
                                                         value = 8,
                                                         step = 0.1)
                        ),
                 checkboxInput('filter_repaid',
                               "Filter repaid loans",
                               value = TRUE)
                 ),
  helpText("Developed by ", 
           a("Sam Abbott", href = "http://samabbott.co.uk"), ".",
           style = "padding-left:1em; padding-right:1em;position:absolute; bottom:1em; ")
)

body <- dashboardBody(
  tabItems(
    tabItem(tabName = "readme",
            withMathJax(), 
            includeMarkdown("README.md")
    ),
    tabItem(tabName = "fc_dashboard",
            fluidRow(
              tags$head(includeScript("google-analytics.js")),
              tabBox( width = 12,
                      title = "Summary Plots",
                      side = "right",
                      tabPanel(title = "Summary",
                               plotlyOutput("fc_plotsummary", height="200%")),
                      tabPanel(title = "By Year",
                               plotlyOutput("fc_plottotal", height = "200%"),
                               selectInput("fc_round_date", 
                                           "Time to aggregate by:",
                                           list(Year = "year",
                                                Month = "month",
                                                Week =  "week",
                                                Day = "day"))
                               ),
                      tabPanel(title = "By Stratified Variable",
                               plotlyOutput("fc_plotdist", height = "200%")
                               ),
                      tabPanel(title = "Variable vs. Variable",
                               plotlyOutput("fc_plotscatter", height = "200%"),
                               selectInput("fc_com_var", 
                                           "Variable to compare against:",
                                           list(`Interest rate` = "interest_rate",
                                                `Loan amount` = 
                                                  "loan_amount",
                                                Recoveries = 
                                                  "recoveries",
                                                `Principal remaining` = 
                                                  "principal_remaining",
                                                Defaulted = "defaulted",
                                                `Payments remaining` = "payments_remaining",
                                                `Term` = "term"
                                           )))),
            infoBoxOutput("fc_amount_lent"),
            infoBoxOutput("fc_repaid"),
            infoBoxOutput("fc_defaulted"),
            infoBoxOutput("fc_recovered")
    )
    ),
    tabItem(tabName = "p_dashboard",
            fluidRow(
              box(title = "Overview",
                  solidHeader = FALSE,
                  tableOutput("p_loanbook_overview"),
                  footer = "* The adjusted interest rate accounts for the 1% Funding Circle fee and estimated
                  bad debt (settable in the options menu).",
                  width = 12
                  ),
              column(width = 6,
                     tabBox( width = NULL,
                             title = "Summary Plots",
                             side = "right",
                             tabPanel(title = "Amount lent (£)",
                                      plotlyOutput("p_loanbook_sum_plot_amount", height = "200%")),
                             tabPanel(title = "No. of loan parts",
                                      plotlyOutput("p_loanbook_sum_plot_no", height = "200%")),
                             tabPanel(title = "Percentage of loanbook (%)",
                                      plotlyOutput("p_loanbook_sum_plot_per", height = "200%"))
                     )
              ),
              column(width = 6,
                     tabBox( width = NULL,
                             title = "Summary Tables",
                             side = "right",
                             tabPanel(title = "Summary",
                                      DT::dataTableOutput("p_loanbook_sum_table")),
                             tabPanel(title = "Loanbook",
                                      DT::dataTableOutput("p_loanbook_table", width = "auto")
                             ))
              )
            )
    ),
    tabItem(tabName = "p_exploratory",
            fluidRow(
              tags$head(includeScript("google-analytics.js")),
              tabBox( width = 12,
                      title = "Summary Plots",
                      side = "right",
                      tabPanel(title = "Summary",
                               plotlyOutput("p_plotsummary", height = "200%")),
                      tabPanel(title = "By Year",
                               plotlyOutput("p_plottotal", height = "200%"),
                               selectInput("p_round_date", 
                                           "Time to aggregate by:",
                                           list(Year = "year",
                                                Month = "month",
                                                Week =  "week",
                                                Day = "day"))),
                      tabPanel(title = "By Stratified Variable",
                               plotlyOutput("p_plotdist", height = "200%")),
                      tabPanel(title = "Variable vs. Variable",
                               plotlyOutput("p_plotscatter", height = "200%"),
                               selectInput("p_com_var", 
                                           "Variable to compare against:",
                                           list(`Interest rate` = "interest_rate",
                                                `Loan amount` = 
                                                  "loan_amount",
                                                Recoveries = 
                                                  "recoveries",
                                                `Principal remaining` = 
                                                  "principal_remaining",
                                                Defaulted = "defaulted",
                                                `Payments remaining` = "payments_remaining",
                                                `Term` = "term"
                                           )))),
              infoBoxOutput("p_amount_lent"),
              infoBoxOutput("p_repaid"),
              infoBoxOutput("p_defaulted"),
              infoBoxOutput("p_recovered")
            )
    ),
    tabItem(tabName = "fc_pca",
            fluidRow(
              tabBox( width = 12,
                      title = "Principal Components",
                      side = "right",
                      tabPanel(title = "Scatter",
                               plotlyOutput("plot_fc_pca", height = "200%"))
              )
            )
            ),
   tabItem(tabName = "p_pca",
          fluidRow(
            tabBox( width = 12,
                    title = "Principal Components",
                    side = "right",
                    tabPanel(title = "Scatter",
                             plotlyOutput("plot_p_pca", height = "200%"))
            )
          )
  ),
    tabItem(tabName = "dataclean",
            box( width = NULL, status = "primary", solidHeader = TRUE, title="Data Cleaning of FC Loanbook",                
                 downloadButton('downloadData0', 'Download'),
                 br(),br(),
                 pre(includeText("clean_fc_loanbook.R"))
            )
    ),
    tabItem(tabName = "utility_functions",
            box( width = NULL, status = "primary", solidHeader = TRUE, title="Utility Functions",                
                 downloadButton('downloadData1', 'Download'),
                 br(),br(),
                 pre(includeText("utility_functions.R"))
            )
    ),
  tabItem(tabName = "personal_loanbook",
          box( width = NULL, status = "primary", solidHeader = TRUE, title="Personal Loanbook Functions",                
               downloadButton('downloadData2', 'Download'),
               br(),br(),
               pre(includeText("personal_loanbook.R"))
          )
  ),
    tabItem(tabName = "ui",
            box( width = NULL, status = "primary", solidHeader = TRUE, title="UI",
                 downloadButton('downloadData3', 'Download'),
                 br(),br(),
                 pre(includeText("ui.R"))
            )
    ),
    tabItem(tabName = "server",
            box( width = NULL, status = "primary", solidHeader = TRUE, title="Server",
                 downloadButton('downloadData4', 'Download'),
                 br(),br(),
                 pre(includeText("server.R"))
            )
    )
  )
)

dashboardPage(
  dashboardHeader(title = "FC Dashboard"),
  sidebar,
  body,
  skin = "black"
)

Server

Download

#Load packages
library(shiny)
library(shinydashboard)
library(shinyBS)
library(shinyWidgets)
library(DT)
library(tidyverse)
library(rmarkdown)
library(caret)
library(ggfortify)
library(plotly)
library(lubridate)
library(wrapr)
library(stringr)

## Source cleaned data
source("clean_fc_loanbook.R")

## Source utility functions
source("utility_functions.R")

## Source functions for personal loanbook
source("personal_loanbook.R")

## Stop spurious warnings
options(warn = -1)

## Increase upload limit
options(shiny.maxRequestSize = 10*1024^2) 

shinyServer(function(input, output) {

  ##Input menu items to output menu items
  fc_yaxis <- reactive({input$fc_yaxis})
  
  ## Clean/Load FC data
  clean_fc_loanbook <- reactive(
    load_clean_loanbook(input$loanbook,ref_date = input$ref_date)
    )
  
  ##Clean/Load personal data
  clean_personal_loanbook <- reactive(
    loan_clean_personal_loanbook(input$personal_loanbook)
  )
  
  ## Set up reactive filtering slider
  output$date_slider <- renderUI({
    sliderInput(inputId = 'dates', 
                label = 'Time Range',
                min = min(clean_fc_loanbook()$ref_date),
                max = max(clean_fc_loanbook()$ref_date),
                value = range(clean_fc_loanbook()$ref_date),
                timeFormat = "%b %Y")
    })

  ## Filter data
  fc_loanbook <- reactive(
    clean_fc_loanbook() %>% 
      filter(ref_date >= input$dates[1],
             ref_date <= input$dates[2])
  )
  
  combined_loanbook <- reactive(
    clean_personal_loanbook() %>%
      bind_loanbooks(fc_loanbook(), verbose = TRUE)  %>% 
      filter(ref_date >= input$dates[1],
             ref_date <= input$dates[2])
  )
  
  p_loanbook <- reactive(
    combined_loanbook() %>% 
      filter(invested_in %in% "Yes") %>% 
      mutate(`Loan ID` = id) %>% 
      mutate(Region = region_name,
             `Repayment type` = repayment_type,
             `Security taken` = security_taken,
             `Loan term` = term,
             `Loan purpose` = loan_purpose,
              Year = year,
             `Grouped loan amount` = grouped_loan_amount)
  )
  
  ## Set up reactive filtering variable - funding circle loanbook dash
  output$filter_var_picker_fc_dash <- renderUI({
    if (input$fc_dash_filter %in% "no_filter") {
      choices <- NULL
    }else{
      choices <- clean_fc_loanbook()[[input$fc_dash_filter]] %>%
        as.character %>% 
        unique %>% 
        as.list
    }
    
    pickerInput(
      inputId = "fc_dash_filt_var", 
      label = "Select/deselect all options", 
      choices = choices, options = list(`actions-box` = TRUE),
      multiple = TRUE,
      width = "auto"
    )
  })
  
  output$filter_var_picker_fc_dash_2 <- renderUI({
    if (input$fc_dash_filter_2 %in% "no_filter") {
      choices <- NULL
    }else{
      choices <- clean_fc_loanbook()[[input$fc_dash_filter_2]] %>%
        as.character %>% 
        unique %>% 
        as.list
    }
    
    pickerInput(
      inputId = "fc_dash_filt_var_2", 
      label = "Select/deselect all options", 
      choices = choices, options = list(`actions-box` = TRUE),
      multiple = TRUE,
      width = "auto"
    )
  })
  
  
  ## Set up reactive filtering variable - personal loanbook dash
  output$filter_var_picker <- renderUI({
    if (input$p_dash_filter %in% "no_filter") {
     choices <- NULL
    }else{
      choices <- p_loanbook()[[input$p_dash_filter]] %>%
        as.character %>% 
        unique %>% 
        as.list
    }

    pickerInput(
      inputId = "p_dash_filt_var", 
      label = "Select/deselect all options", 
      choices = choices, options = list(`actions-box` = TRUE),
      multiple = TRUE,
      width = "auto"
    )
  })
  
  output$filter_var_picker_2 <- renderUI({
    if (input$p_dash_filter_2 %in% "no_filter") {
      choices <- NULL
    }else{
      choices <- p_loanbook()[[input$p_dash_filter_2]] %>%
        as.character %>% 
        unique %>% 
        as.list
    }
    
    pickerInput(
      inputId = "p_dash_filt_var_2", 
      label = "Select/deselect all options", 
      choices = choices, options = list(`actions-box` = TRUE),
      multiple = TRUE,
      width = "auto"
    )
  })
  
  ##Set up reactive filtering for personal loanbook exploratory
  output$filter_var_picker_p_exp <- renderUI({
    if (input$p_exp_filter %in% "no_filter") {
      choices <- NULL
    }else{
      choices <- p_loanbook()[[input$p_exp_filter]] %>%
        as.character %>% 
        unique %>% 
        as.list
    }
    
    pickerInput(
      inputId = "p_exp_filt_var", 
      label = "Select/deselect all options", 
      choices = choices, options = list(`actions-box` = TRUE),
      multiple = TRUE,
      width = "auto"
    )
  })
  
  output$filter_var_picker_p_exp_2 <- renderUI({
    if (input$p_exp_filter_2 %in% "no_filter") {
      choices <- NULL
    }else{
      choices <- p_loanbook()[[input$p_exp_filter_2]] %>%
        as.character %>% 
        unique %>% 
        as.list
    }
    
    pickerInput(
      inputId = "p_exp_filt_var_2", 
      label = "Select/deselect all options", 
      choices = choices, options = list(`actions-box` = TRUE),
      multiple = TRUE,
      width = "auto"
    )
  })
  
  ## Filter fc loanbook for dashboard
  filt_fc_loanbook <- reactive({
    filt_loanbook <- fc_loanbook()
    
    if (!input$fc_dash_filter %in% "no_filter") {
      filt_loanbook <- filt_loanbook %>% 
        filter_at(.vars = c(input$fc_dash_filter), 
                  all_vars(. %in% input$fc_dash_filt_var)
        )
    }else {
      filt_loanbook <- filt_loanbook
    }
    
    if (!input$fc_dash_filter_2 %in% "no_filter") {
      filt_loanbook <- filt_loanbook %>% 
        filter_at(.vars = c(input$fc_dash_filter_2), 
                  all_vars(. %in% input$fc_dash_filt_var_2)
        )
    }else {
      filt_loanbook <- filt_loanbook
    }
  })
  
  ## Clean loan book for dashboard: note repaid loans are dropped here
  ## This means that the dashboard represents your loanbook as it is now
  ## if filtering is selected, the filter loanbook
  cleaned_p_loanbook <- reactive({
clean_loanbook <- p_loanbook() %>% 
      select(`Loan ID`, `Loan title`, `Sector`,
             `Number of loan parts`, Risk, `Loan status`,
             `Repayments made`, `Repayments left`, `Percentage repaid`,
             `Principal remaining`, Rate, `Next payment date`,
             `Loan term`, `Loan purpose`, Region, `Repayment type`, 
             `Security taken`,`Grouped loan amount`, day, day_of_week, week, month, year)

if (input$filter_repaid) {
  clean_loanbook <-  clean_loanbook  %>% 
    filter(!`Loan status` %in% "Repaid")
}else{
  clean_loanbook <- clean_loanbook
}

if (!input$p_dash_filter %in% "no_filter") {
  clean_loanbook <- clean_loanbook %>% 
    filter_at(.vars = c(input$p_dash_filter), 
              all_vars(. %in% input$p_dash_filt_var)
    )
}else {
  clean_loanbook <- clean_loanbook
}

if (!input$p_dash_filter_2 %in% "no_filter") {
  clean_loanbook <- clean_loanbook %>% 
    filter_at(.vars = c(input$p_dash_filter_2), 
              all_vars(. %in% input$p_dash_filt_var_2)
    )
}else {
  clean_loanbook <- clean_loanbook
}

})
  
## Filter personal loanbook for exploratory
  filt_p_loanbook <- reactive({
    filt_loanbook <- p_loanbook()
    
    if (!input$p_exp_filter %in% "no_filter") {
      filt_loanbook <- filt_loanbook %>% 
        filter_at(.vars = c(input$p_exp_filter), 
                  all_vars(. %in% input$p_exp_filt_var)
        )
    }else {
      filt_loanbook <- filt_loanbook
    }
    
    if (!input$p_exp_filter_2 %in% "no_filter") {
      filt_loanbook <- filt_loanbook %>% 
        filter_at(.vars = c(input$p_exp_filter_2), 
                  all_vars(. %in% input$p_exp_filt_var_2)
        )
    }else {
      filt_loanbook <- filt_loanbook
    }
    
    if (input$p_exp_filter_repaid) {
      filt_loanbook <-  filt_loanbook  %>% 
        filter(!status %in% "repaid")
    }else{
      filt_loanbook <- filt_loanbook
    }
    
  })
  
  ##Summary stats
  fc_sumstats <- reactive(
    summary_stats(filt_fc_loanbook())
  )

  ##Summary stats
  p_sumstats <- reactive(
    summary_stats(filt_p_loanbook())
  )
  
  ## Exploratory plots
  ## plot loanbook summary - fc
  output$fc_plotsummary <- renderPlotly({
  filt_fc_loanbook()  %>%
      summarise_loanbook(yvar = input$fc_yaxis,
                         strat = input$fc_strat_var,
                         facet = input$fc_facet_var) %>% 
      plot_loanbook_summary(yvar = input$fc_yaxis, 
                              strat = input$fc_strat_var,
                              facet = input$fc_facet_var,
                              scaled_to_mil = TRUE,
                              plotly = TRUE)
  })
  
  
  ## plot loanbook summary - personal
  output$p_plotsummary <- renderPlotly({
    filt_p_loanbook()  %>%
      summarise_loanbook(yvar = input$p_yaxis,
                         strat = input$p_strat_var,
                         facet = input$p_facet_var) %>% 
      plot_loanbook_summary(yvar = input$p_yaxis, 
                            strat = input$p_strat_var,
                            facet = input$p_facet_var,
                            scaled_to_mil = TRUE,
                            plotly = TRUE)
  })
  
  ## Plot total lent by time
  output$fc_plottotal <- renderPlotly(
      plot_by_date(filt_fc_loanbook(), 
                   by = input$fc_yaxis, 
                   strat = input$fc_strat_var,
                   facet = input$fc_facet_var,
                   plotly = TRUE,
                   round_date = input$fc_round_date)

  )
  
  output$p_plottotal <- renderPlotly(
      plot_by_date(filt_p_loanbook(), 
                   by = input$p_yaxis, 
                   strat = input$p_strat_var,
                   facet = input$p_facet_var,
                   plotly = TRUE,
                   round_date = input$p_round_date)
  )
  
  ## Plot amount as violin
  output$fc_plotdist <- renderPlotly(
      plot_dist(filt_fc_loanbook(), 
                   by = input$fc_yaxis, 
                   strat = input$fc_strat_var,
                   facet = input$fc_facet_var,
                   plotly = TRUE)
  )
  
  output$p_plotdist <- renderPlotly(
      plot_dist(filt_p_loanbook(), 
                by = input$p_yaxis, 
                strat = input$p_strat_var,
                facet = input$p_facet_var,
                plotly = TRUE)
  )
  
  ## Plot variable scatter
  output$fc_plotscatter <- renderPlotly(
plot_scatter(filt_fc_loanbook(), 
                 by = input$fc_yaxis, 
                 also_by = input$fc_com_var,
                 strat = input$fc_strat_var,
                 facet = input$fc_facet_var,
                 plotly = TRUE)
  )

  
  output$p_plotscatter <- renderPlotly(
    plot_scatter(filt_p_loanbook(), 
                 by = input$p_yaxis, 
                 also_by = input$p_com_var,
                 strat = input$p_strat_var,
                 facet = input$p_facet_var,
                 plotly = TRUE,
                 alpha = 0.8)
  )
  
  ## Amount Lent
  output$fc_amount_lent <- renderInfoBox(
    infoBox("Amount Lent", fc_sumstats() %>% 
              select(amount_lent) %>% 
      convert_million,
      color = "black")
  )
  
  output$p_amount_lent <- renderInfoBox(
    infoBox("Amount Lent", p_sumstats() %>% 
              select(amount_lent) %>% 
              convert_million,
            color = "black")
  )
  
  ## Amount repaid
  output$fc_repaid <- renderInfoBox(
    infoBox("Amount Repaid", return_with_per(fc_sumstats(), principal_repaid,
                                                amount_lent),
            color = "black")
  )
  
  output$p_repaid <- renderInfoBox(
    infoBox("Amount Repaid", return_with_per(p_sumstats(), principal_repaid,
                                             amount_lent),
            color = "black")
  )
  
  ## Amount defaulted
  output$fc_defaulted <- renderInfoBox(
    infoBox("Amount Defaulted", return_with_per(fc_sumstats(), defaulted,
                                                amount_lent),
            color = "black")
  )
 
  output$p_defaulted <- renderInfoBox(
    infoBox("Amount Defaulted", return_with_per(p_sumstats(), defaulted,
                                                amount_lent),
            color = "black")
  ) 
  
  ## Amount recovered
  output$fc_recovered <- renderInfoBox(
    infoBox("Amount Recovered", return_with_per(fc_sumstats(), recoveries,
                                                defaulted), 
            color = "black")
  )
  
  ## Amount recovered
  output$p_recovered <- renderInfoBox(
    infoBox("Amount Recovered", return_with_per(p_sumstats(), recoveries,
                                                defaulted), 
            color = "black")
  )
  
  ##PCA
  fc_pca <- reactive(
    fc_loanbook() %>% 
      pca_on_loanbook(no_pca = input$fc_no_pca)
  )
  
  p_pca <- reactive(
    p_loanbook() %>% 
      pca_on_loanbook(no_pca = input$p_no_pca)
  )
  
  ## plot pca
  output$plot_fc_pca <- renderPlotly(
    plot_pca(fc_pca(), 
             pc_1 = input$fc_pca_1, 
             pc_2 = input$fc_pca_2,
             strat = input$fc_strat_var2, 
             plotly = TRUE)
  )
  
  ## plot pca
  output$plot_p_pca <- renderPlotly(
    plot_pca(p_pca(), 
             pc_1 = input$p_pca_1, 
             pc_2 = input$p_pca_2,
             strat = input$p_strat_var2, 
             plotly = TRUE,
             alpha = 0.8)
  )
  
  ## Personal Dashboard
  
  ## Loanbook overview
  output$p_loanbook_overview <- renderTable(
    p_loanbook_overall_sum_info(cleaned_p_loanbook(),
                                aplus_bad = input$aplus_bad,
                                a_bad = as.double(input$a_bad),
                                b_bad = as.double(input$b_bad),
                                c_bad = as.double(input$c_bad),
                                d_bad = as.double(input$d_bad),
                                e_bad = as.double(input$e_bad))
  )
  
  ## Raw data table
  output$p_loanbook_table <- DT::renderDataTable(
    cleaned_p_loanbook(),
    options = list(
      pageLength = 5,
      scrollX = TRUE,
      scrollY = TRUE,
      rownames = FALSE)
  )
  
  ## Summarised personal loanbook
  p_sum_tab <- reactive(
    cleaned_p_loanbook() %>% 
      p_loanbook_sum_table(strat = input$p_dash_strat)
  )
  ##Summarise facet personalised loanbook
  p_sum_tab_strat <- reactive({
    if (input$p_dash_facet %in%  "no_facet") {
      strat <- input$p_dash_strat
    }else {
      strat <- c(input$p_dash_strat, input$p_dash_facet)
    }
    
    cleaned_p_loanbook() %>% 
      p_loanbook_sum_table(strat = strat)
  })
  
  ## Summarised data table
  output$p_loanbook_sum_table <- DT::renderDataTable(
    p_sum_tab_strat(),
    options = list(
      pageLength = 15,
      scrollX = TRUE,
      scrollY = TRUE,
      orderClasses = TRUE,
      rownames = FALSE)
  )
  
  ## Summary plots of loan book make up
  output$p_loanbook_sum_plot_amount <- renderPlotly(
    p_sum_tab_strat() %>%
      plot_loanbook_summary(yvar = "`Amount lent (£)`", 
                              strat = input$p_dash_strat,
                              facet = input$p_dash_facet,
                              plotly = TRUE)
  )
  
  output$p_loanbook_sum_plot_no <- renderPlotly(
    p_sum_tab_strat() %>%  
      plot_loanbook_summary(yvar = "`Number of loan parts`", 
                              strat = input$p_dash_strat,
                              facet = input$p_dash_facet,
                              plotly = TRUE)
  )
  
  output$p_loanbook_sum_plot_per <- renderPlotly(
    p_sum_tab_strat() %>% 
      plot_loanbook_summary(yvar = "`Percentage of loanbook (%)`", 
                              strat = input$p_dash_strat,
                              facet = input$p_dash_facet,
                              plotly = TRUE)
  )

  ## Downloads from scripts
  ## Set up downloadable scripts
  output$downloadData0 <- downloadHandler(filename = "clean_fc_loanbook.R",
                                          content = function(file) {
                                            file.copy("clean_fc_loanbook.R", file, overwrite = TRUE)
                                          }
  )
  output$downloadData1 <- downloadHandler(filename = "utility_functions.R",
                                          content = function(file) {
                                            file.copy("utility_functions.R", file, overwrite = TRUE)
                                            }
                                          )
  output$downloadData2 <- downloadHandler(filename = "personal_loanbook.R",
                                          content = function(file) {
                                            file.copy("personal_loanbook.R", file, overwrite = TRUE)
                                          }
  )
  output$downloadData3 <- downloadHandler(filename = "ui.R",
                                          content = function(file) {
                                            file.copy("ui.R", file, overwrite = TRUE)
                                            }
                                          )
  output$downloadData4 <- downloadHandler(filename = "server.R",
                                          content = function(file) {
                                            file.copy("server.R", file, overwrite = TRUE)
                                            }
                                          )
  
})