---
title: "Introduction to Huxtable"
author: "David Hugh-Jones"
date: '`r Sys.Date()`'
output:
  html_document:
    toc: yes
    toc_depth: 2
  pdf_document:
    includes:
      in_header: placeins-header.tex
    toc: yes
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{Introduction to Huxtable}   
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}   
---


```{r setup, echo = FALSE, warning = FALSE, message = FALSE}

library(knitr)
library(dplyr)
library(huxtable)
options(huxtable.knit_print_df = FALSE)

is_latex <- guess_knitr_output_format() == 'latex'
# is_latex <- TRUE
knitr::knit_hooks$set(
  barrier = function(before, options, envir) {
    if (! before && is_latex) knitr::asis_output('\\FloatBarrier')
  }
)

if (is_latex) knitr::opts_chunk$set(barrier = TRUE)

```


```{r, echo = FALSE}
huxtable::hux_logo(latex = is_latex, html = ! is_latex)
```

# Introduction

## About this document

This is the introductory vignette for the R package 'huxtable', version `r packageVersion('huxtable')`. A current
version is available on the web in [HTML](https://hughjonesd.github.io/huxtable/huxtable.html) or 
[PDF](https://hughjonesd.github.io/huxtable/huxtable.pdf) format.

## Huxtable

Huxtable is a package for creating *text tables*. It is powerful, but easy to use. Huxtable's
features include:

* Export to LaTeX, HTML, Microsoft Word, Microsoft Excel, Microsoft Powerpoint, RTF and Markdown
* Easy integration with knitr and rmarkdown documents
* Formatted on-screen display
* Multirow and multicolumn cells
* Fine-grained control over cell background, spacing, alignment, size and borders
* Control over text font, style, size, colour, alignment, number format and rotation
* Table manipulation using standard R subsetting, or dplyr functions like `filter` and `select`
* Easy conditional formatting based on table contents
* Quick table themes
* Automatic creation of regression output tables with the `huxreg` function

We will cover all of these features below.

## Installation

If you haven't already installed huxtable, you can do so from the R command line:

```{r, eval = FALSE}
install.packages('huxtable')
```


## Getting started

A huxtable is an R object representing a table of text. You already know that R can represent a
table of data in a data frame. For example, if `mydata` is a data frame, then `mydata[1, 2]` represents the
the data in row 1, column 2, and `mydata$start_time` is all the data in the `start_time` column.

A huxtable is just a data frame with some extra properties. So, if `myhux` is a huxtable, then `myhux[1, 2]`
represents the data in row 1 column 2, as before. But this cell will also have some other properties - for
example, the font size of the text, or the colour of the cell border.

To create a huxtable, use the function `huxtable`, or `hux` for short. This works very much like
`data.frame`:

```{r}
library(huxtable)
ht <- hux(
        Employee     = c('John Smith', 'Jane Doe', 'David Hugh-Jones'), 
        Salary       = c(50000L, 50000L, 40000L),
        add_colnames = TRUE
      )
```


You can convert a data frame to a huxtable with `as_hux`.

```{r}
data(mtcars)
car_ht <- as_hux(mtcars)
```

If you look at a huxtable in R, it will print out a simple representation of the data. Notice that we've added the
column names to the data frame itself, using the `add_colnames` argument to `hux`. We're going to print them out, so they need to be part of the actual table. **NB:** This means that the data will start on row 2 of the huxtable, and the
column names will be row 1.

```{r, results = 'markup'}
print_screen(ht)     # on the R command line, you can just type "ht"
```

To print a huxtable as LaTeX or HTML, just call `print_latex` or `print_html`. In knitr
documents, like this one, you can simply evaluate the huxtable:


```{r}
ht
```


# Changing the look and feel

## Huxtable properties

The default output is a plain table. Let's make it smarter. We'll make the table headings
bold, draw a line under the header row, add some horizontal space to the cells, and change
the number formatting.

To do this, we will set some **properties** on the table cells. You set properties by assigning
to the property name, just as you assign `names(x) <- new_names` in base R. The following commands
assign the value 10 to the `right_padding` and `left_padding` properties, for all cells in `ht`:

```{r}
right_padding(ht) <- 10
left_padding(ht)  <- 10
```

We can set the `number_format` property to change how numbers are displayed:

```{r}
number_format(ht) <- 2    # 2 decimal places
```

To assign properties to just some cells, you use subsetting, as in base R. So, to make the
first row of the table **bold** and give it a bottom border, we do:

```{r}
bold(ht)[1, ]          <- TRUE
bottom_border(ht)[1, ] <- 1
```

After these changes, our table looks smarter:

```{r}
ht
```


So far, all these properties have been set at cell level. Different cells can have different
alignment, text formatting and so on. By contrast, `caption` is a table-level property. It only
takes one value, which sets a table caption.

```{r}

caption(ht) <- 'Employee table'
ht

```


As well as cell properties and table properties, there is also one row property, `row_height`, and
one column property, `col_width`.

The table below shows a complete list of properties. 

```{r, echo = FALSE}
sides <- c('left_', 'right_', 'top_', 'bottom_')
props <- list()
props[['Cell_Text']] <- sort(c('font', 'text_color', 'wrap', 'bold', 'italic', 'font', 'font_size', 'na_string', 'escape_contents', 'number_format', 'rotation'))

props[['Cell']] <- sort(c('align', 'valign', 'rowspan', 'colspan', 'background_color', 
      paste0(sides, 'border'), paste0(sides, 'border_color'), paste0(sides, 'border_style'), 
      paste0(sides, 'padding')))
props[['Row']]    <- 'row_height'
props[['Column']] <- 'col_width'
props[['Table']]  <- sort(c('width', 'height', 'position', 'caption', 'caption_pos', 'tabular_environment', 'label', 'latex_float'))

maxl <- max(sapply(props, length))
props <- lapply(props, function(x) c(x, rep('', maxl - length(x))))

ss_font <- if (guess_knitr_output_format() == 'latex') 'cmtt' else 'courier'

prop_hux <- hux(as.data.frame(props))                     %>% 
      add_colnames                                        %>% 
      {foo <- .; foo[1,] <- gsub('_', ' ', foo[1,]); foo} %>% 
      set_font(-1, everywhere, ss_font)                   %>% 
      set_font_size( 10)                                  %>% 
      set_bold(1, everywhere, TRUE)                       %>% 
      set_width(0.9)                                      %>% 
      set_background_color(-1, evens, grey(.9))           %>% 
      set_outer_borders(1)                                %>% 
      set_bottom_border(1, everywhere, 1)                 %>% 
      set_top_padding(2)                                  %>% 
      set_bottom_padding(4)                               %>% 
      set_caption('Huxtable properties')                  %>% 
      set_position('left') %>% 
      set_col_width(c(.2, .25, .15, .15, .25))

prop_hux
```


## Tidyverse syntax

If you prefer a tidyverse style of code, using the pipe operator `%>%`, then you can use `set_*`
functions to set properties. These are named like `set_xxx` where `xxx` is the property name, 
for example `set_bold` for the `bold` property.

`set_*` functions return the modified huxtable, so you can chain them together like this:

```{r}

library(dplyr)
hux(
        Employee     = c('John Smith', 'Jane Doe', 'David Hugh-Jones'), 
        Salary       = c(50000, 50000, 40000),
        add_colnames = TRUE
      )                               %>%
      set_right_padding(10)           %>%
      set_left_padding(10)            %>% 
      set_bold(1, 1:2, TRUE)          %>% 
      set_bottom_border(1, 1:2, 1)    %>%
      set_align(1:4, 2, 'right')      %>%
      set_number_format(2)            %>% 
      set_caption('Employee table')

```


`set_*` functions for cell properties are called like this: `set_xxx(ht, row, col, value)` or like
this: `set_xxx(ht, value)`. If you use the second form, then the value is set for all cells. `set_*`
functions for table properties are always called like `set_xxx(ht, value)`. 

There are also some useful convenience functions:

* `set_all_borders` sets left, right, top and bottom borders for selected cells;
* `set_all_border_colors` sets left, right, top and bottom border colors;
* `set_all_border_styles` sets left, right, top and bottom border styles;
* `set_all_padding` sets left, right, top and bottom padding (the amount of space between the content
  and the border);
* `set_outer_borders`, `set_outer_border_colors` and `set_outer_border_styles` set an outer border
  around a rectangle of cells.

## Getting properties

To get the current properties of a huxtable, just use the properties function without the left arrow:

```{r, results = 'markup'}
italic(ht)
position(ht)
```


# Editing content


## Changing and adding content

You can treat a huxtable just like a data frame. If you want to change data in a cell, assign to
that cell:

```{r}
ht[3, 1] <- 'Jane Jones'
ht
```

To add a column, do, e.g.:

```{r}
ht_with_roles <- ht
ht_with_roles$Role <- c("Role", "Admin", "CEO", "Dogsbody")
ht_with_roles
```


Notice that the third column doesn't have the properties we set on the first two columns, like the
bold first row and the underlining.

If we want new columns to copy properties from their neighbours, we can use `cbind`, a base R
function that binds columns together. When you `cbind` huxtable objects, by default, cell properties
are copied over from their neighbours:

```{r}
ht_with_roles <- cbind(ht, c("Role", "Admin", "CEO", "Dogsbody"))
ht_with_roles
```

`rbind` works the same way:

```{r}
rbind(ht, c("Yihui Xie", 100000))
```

Notice how Yihui's salary has got the same number formatting as the other employees. That's because
cell properties for the new row were copied from the row above.

Sometimes, you would like to insert rows or columns in the middle of
a table. You can do this with rbind, but it is not very convenient:

```{r}

to_insert <- hux(
        Role  = c("Admin", "CEO", "Dogsbody"),
        Hired = as.Date(c("2015-01-01", "2008-06-05", "2012-07-31")),
        add_colnames = TRUE
      ) %>% 
      set_bold(1, 1:2, TRUE) %>% 
      set_bottom_border(1, 1:2, TRUE)

cbind(ht[, 1], to_insert, ht[, 2:ncol(ht)])
```

It's more elegant to use huxtable's `add_columns` function:

```{r}

add_columns(ht, to_insert, after = 1)

```

The `after` argument says where the second object should be inserted. 
`after` can also be a column name:

```{r}

add_columns(ht, to_insert, after = "Employee")

```

The function `add_rows` works in the same way.

## Editing content the base R way

You can subset, sort and data-wrangle a huxtable just like a normal data frame. Cell and 
table properties will be carried over into subsets.

```{r}

car_ht <- as_hux(mtcars)                
car_ht <- huxtable::add_rownames(car_ht, "Car")
# Select columns by name:
car_ht <- car_ht[, c("Car", "mpg", "cyl", "am")] 

# Order by number of cylinders:
car_ht <- car_ht[order(car_ht$cyl), ]

car_ht <- huxtable::add_colnames(car_ht)

# Pretty output, see below: 
theme_plain(car_ht[1:5,])
```


## Editing content the dplyr way

You can also use `dplyr` functions to edit a huxtable:


```{r}

car_ht <- as_hux(mtcars)
car_ht <- huxtable::add_rownames(car_ht, colname = "Car")

car_ht <- car_ht                                          %>%
      slice(1:10)                                         %>% 
      select(Car, mpg, cyl, hp)                           %>% 
      arrange(hp)                                         %>% 
      filter(cyl > 4)                                     %>% 
      rename(MPG = mpg, Cylinders = cyl, Horsepower = hp) %>% 
      mutate(kml = MPG/2.82)                              %>% 
      huxtable::add_colnames()                            

theme_plain(car_ht)
```

In general it is a good idea to prepare your data first, before styling it. For example, it was
easier to sort the `cars_mpg` data by cylinder, before adding a row of column names.

# More formatting 

## Number format

You can change how huxtable formats numbers using `number_format`. Set `number_format` to a number
of decimal places. This affects any numbers found within the cell text. 

```{r}
htn <- hux(c(
        "Some numbers...", 
        11.003, 
        300, 
        12.02, 
        "12.1 **", 
        "mean 11.7 (se 2.3)"
      )) 

number_format(htn) <- 3
theme_plain(htn)
```

To align columns by decimal places, just set the `align` property
to `"."`: 

```{r}
align(htn)[2:6, ] <- "." # not the first row

theme_plain(htn)
```

There is currently no true way to align cells by the decimal point in HTML, and only limited
possibilities in TeX, so this works by right-padding cells with spaces. The output may look better
if you use a fixed width font.


## Automatic formatting

By default, when you create a huxtable using `huxtable` or `as_huxtable`, the package will guess
defaults for number formatting and alignment, based on the type of data in your columns. Numeric
data will be right-aligned or aligned on the decimal point; character data will be left aligned;
and the package will try to set sensible defaults for number formatting. If you want to, you can
turn this off with `autoformat = FALSE`:

```{r}

my_data <- data.frame(
        Employee    = c("John Smith", "Jane Doe", "David Hugh-Jones"), 
        Salary      = c(50000L, 50000L, 40000L),
        Performance = c(8.9, 9.2, 7.8)  
      )

as_hux(my_data, add_colnames = TRUE) # with automatic formatting

as_hux(my_data, add_colnames = TRUE, autoformat = FALSE) # no automatic formatting
```

## Escaping HTML or LaTeX

By default, HTML or LaTeX code will be escaped:

```{r}
code_ht <- if (is_latex) hux(c("Some maths", "$a^b$")) else 
      hux(c("Copyright symbol", "&copy;"))

theme_plain(code_ht)
```

To avoid this, set the `escape_contents` property to `FALSE`.

```{r}
escape_contents(code_ht)[2, 1] <- FALSE

theme_plain(code_ht)
```


## Width and cell wrapping

You can set table widths using the `width` property, and column widths using the `col_width`
property. If you use numbers for these, they will be interpreted as proportions of the table width
(or for `width`, a proportion of the width of the surrounding text). If you use character vectors,
they must be valid CSS or LaTeX widths. The only unit both systems have in common is `pt` for
points.

```{r}
width(ht) <- 0.4
col_width(ht) <- c(.7, .3)
ht
```


It is best to set table width explicitly, then set column widths as proportions.

By default, if a cell contains long contents, it will be stretched. Use the `wrap` property to allow
cell contents to wrap over multiple lines:

```{r}
ht_wrapped <- ht
ht_wrapped[5, 1] <- "David Arthur Shrimpton Hugh-Jones"
wrap(ht_wrapped) <- TRUE
ht_wrapped
```


## Adding row and column names

Just like data frames, huxtables can have row and column names. Often, we want to add these to the
final table. You can do this using either the `add_colnames`/`add_rownames` arguments to
`as_huxtable`, or the `add_colnames()`/`add_rownames()` functions.

```{r}
as_hux(mtcars[1:4, 1:4])                           %>% 
      huxtable::add_rownames(colname = "Car name") %>% 
      huxtable::add_colnames()
```


## Merging cells

Sometimes you want a single cell to spread over more than one row or column: for example, if you
want a heading that covers several different rows.

You can do this by calling `merge_cells(ht, rows, cols)`. `rows` and `cols` should be a contiguous
sequence of numbers. The rectangle of cells `ht[rows, cols]` will be merged. 

When cells in a rectangle are merged, all cells apart from the top left one are hidden, along with
any properties they have. So if you want to set cell properties, you have to target the top left 
cell.

Here, we'll add some row and column headings to the `mtcars` dataset:

```{r}

car_ht <- as_hux(mtcars)
car_ht <- huxtable::add_rownames(car_ht, colname = "Car")
car_ht <- car_ht %>% arrange(cyl) %>% select(1:4)
car_ht <- huxtable::add_colnames(car_ht)

car_ht <- cbind(cylinders = car_ht$cyl, car_ht)
car_ht$cylinders[1]   <- ""
car_ht$cylinders[2]   <- "Four cylinders"
car_ht$cylinders[13]  <- "Six cylinders"
car_ht$cylinders[20]  <- "Eight cylinders"

car_ht <- car_ht %>%  
  merge_cells(2:12, 1) %>% 
  merge_cells(13:19, 1) %>% 
  merge_cells(20:33, 1)


car_ht <- rbind(c("List of cars", "", "", "", ""), car_ht)
car_ht <- merge_cells(car_ht, 1, 1:5)
align(car_ht)[1, 1] <- "center"

car_ht <- theme_plain(car_ht)
right_border(car_ht)[1, 1] <- 0.4
bottom_border(car_ht)[21, 1] <- 0.4
car_ht
```

## Quick themes

Huxtable comes with some predefined themes for formatting. You've already
seen `theme_plain`. Other options include `theme_basic` and (for fun) `theme_mondrian`:

```{r}
theme_mondrian(ht)
```

The ["themes" vignette](themes.html) shows all the available themes.

# Selecting rows, columns and cells


## Row and column functions

If you use the `set_*` style functions, huxtable has some convenience functions for selecting rows and columns. To select all rows, or all columns, use `everywhere` in the row or column specification. To select the last `n` rows or columns, use `final(n)`.

You can also use `dplyr` functions like `starts_with()`, `contains()`, and `matches()` to specify columns by column 
name. For a full list of these functions, see `?select_helpers`.

```{r}
ht %>% set_background_color(everywhere, starts_with("S"), "orange")
```

Lastly, remember that you can set a property for every cell by omitting the `row` and `col`
arguments, like this: `set_background_color(ht, "orange")`.


## Conditional formatting

When you want to apply different formatting to different cells, you can use the `map_xxx` functions.

For example, we could create a striped table like this:

```{r}
ht %>% map_background_color(by_rows("grey90", "grey95"))
```

Or, we could apply a text color to our cars based on their ecological performance:

```{r}

car_ht %>% map_text_color(everywhere, 3, 
        by_ranges(c(15, 25), c("red", "darkgreen", "green"))
      )

```

`by_rows` and `by_ranges` are *mapping functions*.

* `by_rows` applies different properties to
different rows in sequence. 

* `by_ranges` divides its input into ranges, and outputs colours based on
that, like the base R function `cut`. 

Above, we mapped all numbers below 15 to `"red"`,
numbers between 15 and 25 to `"darkgreen"` and numbers above 25 to `"green"`.

The syntax of all `map_xxx` functions is `map_xxx(ht, row, col, fn)`. `ht` is the huxtable,
and `fn` is the mapping function starting with `by`. `row` and `col` are optional row and column
specifiers, just the same as for `set_xxx`.

You can also apply properties for cells that match a string, using the `by_regex` mapping function:

```{r}
ht %>% map_bold(by_regex('Jones' = TRUE))
```

There is a `map_xxx` function for each property `xxx`. See the help pages for other mapping functions.

# Creating a regression table

To create a table of regressions, use `huxreg`:

```{r}

lm1 <- lm(mpg ~ cyl, mtcars)
lm2 <- lm(mpg ~ hp, mtcars)
lm3 <- lm(mpg ~ cyl + hp, mtcars)

huxreg(lm1, lm2, lm3)
```

For more information see the ["huxreg" vignette](huxreg.html).

# Output to different formats

## Automatic pretty-printing of data frames

If you load `huxtable` within a knitr document, it will automatically format data frames for you:


```{r, include = FALSE}
options(huxtable.knit_print_df = TRUE)
```

```{r}
head(mtcars)
```

If you don't want this, you can turn it off by setting the `huxtable.knit_print_df` option:

```{r}
options(huxtable.knit_print_df = FALSE)

head(mtcars) # back to normal
```

```{r, include = FALSE}
options(huxtable.knit_print_df = TRUE)
```

## Using huxtables in knitr and rmarkdown

If you use knitr and rmarkdown in RStudio, huxtable objects should automatically display in the
appropriate format (HTML, LaTeX, or RTF). 

Huxtable needs some LaTeX packages for LaTeX output. The function `report_latex_dependencies()` will
print out a set of `usepackage{...}` statements. If you use Sweave or knitr without
rmarkdown, you can use this function in your LaTeX preamble, to load the packages you need. 

If you want to create Word or Powerpoint documents, install the 
[flextable package](https://cran.r-project.org/package=flextable) from CRAN. Huxtables can then be
automatically printed in Word documents. Or you can convert them to `flextable` objects and include
them in Word or Powerpoint documents.  Similarly, to print tables in an Excel spreadsheet, install
the [openxlsx package](https://cran.r-project.org/package=openxlsx) See `?as_flextable` and
`?as_Workbook` for more details.

You can print a huxtable on screen by typing its name at the command line. Borders, column and row
spans and cell alignment are shown. If the [crayon](https://cran.r-project.org/package=crayon)
package is installed, and your terminal or R IDE supports it, border, text and background colours
are also displayed.

```{r, results = 'markup'}
print_screen(ht)
```


If you need to output to another format, file an 
[issue request](https://github.com/hughjonesd/huxtable) on Github. 

## Quick output commands

Sometimes you quickly want to get your data into a document. To
do this you can use huxtable functions starting with `quick_`:

```{r, echo = FALSE}
quick_commands <- hux(
        Command = c("quick_pdf", "quick_docx", "quick_html", "quick_xlsx", "quick_pptx", 
          "quick_rtf", "quick_latex"), 
        Output = c("PDF document", "Word document", "HTML web page", "Excel spreadsheet", 
          "Powerpoint presentation", "RTF document", "LaTeX document"),
        add_colnames = TRUE
      )
font(quick_commands)[, 1] <- if (is_latex) 'cmtt' else 'Courier'

theme_plain(quick_commands)
```

These are called with one or more huxtable objects (or objects which can be turned into a huxtable,
such as data frames). A new document of the appropriate type will be created and opened. By default
the file will be in the current directory, under a name like e.g. `huxtable-output.pdf`. If the file
already exists, you'll be asked to confirm the overwrite. 

```{r, eval = FALSE}
quick_pdf(mtcars) 
quick_pdf(mtcars, file = 'motorcars data.pdf')
```

# End matter

For more information, see the [website](https://hughjonesd.github.io/huxtable) or 
[github](https://github.com/hughjonesd/huxtable).
