---
title: "Tutorial: Creating FFTs for heart disease"
author: "Nathaniel Phillips and Hansjörg Neth"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
bibliography: fft.bib
csl: apa.csl
vignette: >
  %\VignetteIndexEntry{Tutorial: Creating FFTs for heart disease}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, echo = FALSE}
knitr::opts_chunk$set(collapse = FALSE, 
                      comment = "#>", 
                      prompt = FALSE,
                      tidy = FALSE,
                      echo = TRUE, 
                      message = FALSE,
                      warning = FALSE,
                      # Default figure options:
                      dpi = 100, 
                      fig.align = 'center', 
                      fig.height = 6.0, 
                      fig.width  = 6.5, 
                      out.width = "600px")
```


```{r pkgs, echo = FALSE, message = FALSE, results = 'hide'}
library(FFTrees)
```


## Tutorial: Creating FFTs for heart disease

This tutorial on using the **FFTrees** package follows the examples presented in @phillips2017FFTrees (freely available in [html](https://journal.sjdm.org/17/17217/jdm17217.html) | [PDF](https://journal.sjdm.org/17/17217/jdm17217.pdf)):

- Phillips, N. D., Neth, H., Woike, J. K. & Gaissmaier, W. (2017). 
FFTrees: A toolbox to create, visualize, and evaluate fast-and-frugal decision trees. 
_Judgment and Decision Making_, _12_ (4), 344–368.

In the following, we explain how to use **FFTrees** to create, evaluate and visualize FFTs in four simple steps. 


### Step\ 1: Install and load the FFTrees package

We can install FFTrees from CRAN using `install.packages()`. (We only need to do this once.) 

```{r install-pkg, eval = FALSE}
# Install the package from CRAN:
install.packages("FFTrees")
```

To use the package, we first need to load it into your current R session. 
We load the package using `library()`: 

```{r load-pkg-2, eval = TRUE, message = TRUE}
# Load the package:
library(FFTrees)
```

The **FFTrees** package contains several vignettes that guide through the package's functionality (like this one). 
To open the main guide, run `FFTrees.guide()`: 

```{r load-guide, eval = FALSE}
# Open the main package guide: 
FFTrees.guide()
```


### Step\ 2: Create FFTs from training data (and test on testing data)

In this example, we will create FFTs from a heart disease data set. 
The training data are in an object called `heart.train`, and the testing data are in an object called `heart.test`. For these data, we will predict `diagnosis`, a binary criterion that indicates whether each patent has or does not have heart disease (i.e., is at high-risk or low-risk).

To create an `FFTrees` object, we use the function `FFTrees()` with two main arguments: 

1. `formula` expects a formula indicating a binary criterion variable as a function of one or more predictor variable(s) to be considered for the tree. The shorthand `formula = diagnosis ~ .` means to include all predictor variables. 

2. `data` specifies the training data used to construct the FFTs (which must include the criterion variable). 

Here is how we can construct our first FFTs: 

```{r fft-create, message = FALSE}
# Create an FFTrees object:
heart.fft <- FFTrees(formula = diagnosis ~ .,           # Criterion and (all) predictors
                     data = heart.train,                # Training data
                     data.test = heart.test,            # Testing data
                     main = "Heart Disease",            # General label
                     decision.labels = c("Low-Risk", "High-Risk")  # Decision labels (False/True)
                     )
```

Evaluating this expression runs code that examines the data, optimizes thresholds based on our current goals for each cue, and creates and evaluates `r heart.fft$trees$n`\ FFTs. 
The resulting `FFTrees` object that contains the tree definitions, their decisions, and their performance statistics, are assigned to the `heart.fft`\ object.

#### Other arguments

- `algorithm`: There are two different algorithms available to build FFTs `"ifan"` [@phillips2017FFTrees] and `"dfan"` [@phillips2017FFTrees]. (`"max"` [@martignon2008categorization], and `"zigzag"` [@martignon2008categorization] are no longer supported). 

- `max.levels`: Changes the maximum number of levels that are allowed in the tree.

The following arguments apply when using the "ifan" or "dfan" algorithms for creating new FFTs:

- `goal.chase`: The `goal.chase` argument changes which statistic is maximized during tree construction (for the `"ifan"` and `"dfan"` algorithms). Possible arguments include `"acc"`, `"bacc"`, `"wacc"`, `"dprime"`, and `"cost"`. The default is `"wacc"` with a sensitivity weight of\ 0.50 (which renders it identical to `"bacc"`). 

- `goal`: The `goal` argument changes which statistic is maximized when _selecting_ trees after construction (for the `"ifan"` and `"dfan"` algorithms). Possible arguments include `"acc"`, `"bacc"`, `"wacc"`, `"dprime"`, and `"cost"`.

- `my.tree` or `tree.definitions`: We can define a new tree from a verbal description (as a set of sentences), 
or manually specify sets of FFTs as a data frame (in appropriate format). 
See the [Manually specifying FFTs](FFTrees_mytree.html) vignette for details. 


### Step\ 3: Inspect and summarize FFTs

Now we can inspect and summarize the generated decision trees. 
We will start by printing the `FFTrees` object to return basic information to the console: 

```{r fft-print}
# Print an FFTrees object:
heart.fft
```

The output tells us several pieces of information:

- The tree with the highest weighted sensitivity\ `wacc` with a sensitivity weight of\ 0.5 is selected as the best tree.

- Here, the best tree, FFT\ \#1 uses three cues: `thal`, `cp`, and `ca`.

- Several summary statistics for this tree in training and test data are summarized.

All statistics to evaluate each tree can be derived from a 2\ x\ 2 confusion table:  

```{r fft-confusion-table, out.width="50%", echo = FALSE, fig.cap = "**Table 1**: A 2x2 confusion table illustrating the types of frequency counts for 4 possible outcomes."}
knitr::include_graphics("../inst/confusiontable.jpg")
```

For definitions of all accuracy statistics, see the [accuracy statistics](FFTrees_accuracy_statistics.html) vignette.


### Step\ 4: Visualise the final FFT

Use `plot()` to visualize an FFT (an `FFTrees` object):

```{r fft-plot, fig.width = 6.5, fig.height = 6}
# Plot predictions of the best FFT when applied to test data:
plot(heart.fft,      # An FFTrees object
     data = "test")  # data to use (i.e., either "train" or "test")?
```

#### Other arguments

- `tree`: Which tree in the object should beplotted? To plot a tree other than the best fitting tree (FFT \#1), just specify another tree as an integer (e.g.; `plot(heart.fft, tree = 2)`).

- `data`: For which dataset should statistics be shown? Either `data = "train"` (showing fitting or "Training" performance by default), or `data = "test"` (showing prediction or "Testing" performance).

- `stats`: Should accuracy statistics be shown with the tree? To show only the tree, without any performance statistics, include the argument `stats = FALSE`. 

```{r fft-no-stats, fig.width = 8, fig.height = 4, out.width = "500px"}
# Plot only the tree, without accuracy statistics:
plot(heart.fft, what = "tree")
# plot(heart.fft, stats = FALSE)  #  The 'stats' argument has been deprecated.
```

- `comp`: Should statistics from competitive algorithms be shown in the ROC curve? To remove the performance statistics of competitive algorithms (e.g.; regression, random forests), include the argument `comp = FALSE`. 

- `what`: To show individual cue accuracies (in ROC space), include the argument `what = "cues"`:

```{r fft-cues, fig.width = 6, fig.height = 6, out.width = "500px"}
# Plot cue accuracies (for training data) in ROC space:
plot(heart.fft, what = "cues")
```

See the [Plotting FFTrees](FFTrees_plot.html) vignette for details on plotting FFTs. 


### Additional steps

#### Accessing outputs

An `FFTrees` object contains many different outputs, to see them all, run `names()`

```{r fft-names}
# Show the names of all of the outputs in heart.fft:
names(heart.fft)
```

#### Predicting for new data

To predict classifications for a new dataset, use the standard `predict()` function. 
For example, here's how to predict the classifications for data in the `heartdisease` object (which actually is just a combination of `heart.train` and `heart.test`): 

```{r fft-predict, eval = FALSE}
# Predict classifications for a new dataset:
predict(heart.fft, 
        newdata = heartdisease)
```

#### Defining FFTs in words

To define a specific FFT and apply it to data, we can define a tree by providing its verbal description to the `my.tree` argument: 

```{r fft-my-tree, results = 'hide'}
# Create an FFT manually (from description):
my.heart.fft <- FFTrees(formula = diagnosis ~.,
                        data = heart.train,
                        data.test = heart.test,
                        main = "My Heart FFT",
                        my.tree = "If chol > 350, predict True. 
                                   If cp != {a}, predict False. 
                                   If age <= 35, predict False, otherwise, predict True.")
```

Running this code evaluates `my.tree` for the specified sets of data. 
A visualization of the resulting tree shows its performance summary 
(for the training data): 

```{r plot-my-fft, fig.width = 6.5, fig.height = 6}
plot(my.heart.fft, data = "train")
```

The resulting tree is actually not too bad, although its first node is pretty useless (as it only classifies 3\ cases, all as false alarms). 
Thus, omitting the first node will result in an even simpler FFT that cannot be worse. 
Feel free to verify this ---\ and see the [Manually specifying FFTs](FFTrees_mytree.html) vignette for additional details on defining FFTs from verbal or abstract descriptions. 


## Vignettes

<!-- Table of all vignettes: -->

Here is a complete list of the vignettes available in the **FFTrees** package: 

|   | Vignette | Description |
|--:|:------------------------------|:-------------------------------------------------|
|   | [Main guide: FFTrees overview](guide.html) | An overview of the **FFTrees** package |
| 1 | [Tutorial: FFTs for heart disease](FFTrees_heart.html)   | An example of using `FFTrees()` to model heart disease diagnosis |
| 2 | [Accuracy statistics](FFTrees_accuracy_statistics.html) | Definitions of accuracy statistics used throughout the package |
| 3 | [Creating FFTs with FFTrees()](FFTrees_function.html) | Details on the main `FFTrees()` function |
| 4 | [Manually specifying FFTs](FFTrees_mytree.html)   | How to directly create FFTs without using the built-in algorithms |
| 5 | [Visualizing FFTs](FFTrees_plot.html) | Plotting `FFTrees` objects, from full trees to icon arrays |
| 6 | [Examples of FFTs](FFTrees_examples.html) | Examples of FFTs from different datasets contained in the package |


<!-- eof. -->

## References
