---
title: "Publication-ready plots and tables"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Publication-ready plots and tables}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 6,
  fig.height = 4,
  dpi = 150
)
library(regsensitivity)
library(ggplot2)
```

Getting a sensitivity analysis into a paper means two things: a figure
that survives a journal's production process, and a table in whatever
markup the manuscript is written in. This vignette covers both.

```{r data}
data(bfg2020)
bfg2020$statea <- factor(bfg2020$statea)
w1 <- c("log_area_2010", "lat", "lon", "temp_mean", "rain_mean",
        "elev_mean", "d_coa", "d_riv", "d_lak", "ave_gyi")
form <- avgrep2000to2016 ~ tye_tfe890_500kNI_100_l6 +
    log_area_2010 + lat + lon + temp_mean + rain_mean + elev_mean +
    d_coa + d_riv + d_lak + ave_gyi + statea

res <- regsen_bounds(form, bfg2020, compare = w1,
                      cbar = c(0.1, 0.5, 1))
```

## Figures

`plot()` returns an ordinary `ggplot`, so nothing here is a dead end:
anything the arguments do not cover, you add yourself.

```{r basic}
plot(res)
```

The defaults follow the economics journals: an L of axis lines rather
than a box, no grid, ticks outside the panel, and no title, because the
caption carries it.

### Reading an unbounded identified set

Where the identified set is unbounded, the bounds leave the panel rather
than tracing along its edge. That distinction matters: a line running
flat along the axis reads as "the bound levels off here", which is the
opposite of what an infinite bound means.

```{r unbounded}
plot(res, ylim = c(-10, 14))
```

The green and orange curves exit the top and bottom of the panel. They do
not plateau.

### Reference lines

`xline` is the equivalent of Stata's `xline()`, for marking a threshold
under discussion in the text.

```{r xline}
plot(res, xline = c(0.5, 1))
```

### Sizing for a journal

`base_size` scales the type. For a two-column figure, render at about
3.3 inches wide and pass `base_size = 9`, which puts the type near 8pt on
the page.

```{r sizing, fig.width = 3.3, fig.height = 2.6}
plot(res, base_size = 9, show_legend = FALSE)
```

### Matching your manuscript's font

Fonts are left to you, because what is installed varies by machine and a
missing family would make the figure unreproducible. To match a LaTeX
body type:

```{r font, eval = FALSE}
plot(res) + theme_regsen(base_family = "Times New Roman")
```

### Colour, greyscale and accessibility

The palette is Okabe-Ito, which stays distinguishable under the common
forms of colour vision deficiency. Series are also encoded by line type,
so the figure still reads when a journal prints it in greyscale --
colour alone would not survive that.

```{r greyscale}
plot(res) + scale_colour_grey(start = 0, end = 0.6)
```

### Overriding anything

```{r override}
plot(res, subtitle = NA) +
    theme_regsen(grid = "y", base_size = 10) +
    labs(caption = "BFG (2020); bounds under DMP (2026).")
```

## Tables

### The tidy route

`as.data.frame()` gives the results as a plain data frame. This is the
recommended entry point: it hands the numbers to whichever table package
you already use, rather than tying the package to one of them.

```{r asdf}
head(as.data.frame(res, digits = 3))
```

From here `kableExtra`, `gt`, `modelsummary`, `huxtable`, `tinytable` and
`xtable` all work as usual.

### The convenience route

`regsen_table()` covers the common case in one call. The `format`
argument follows the document you are knitting to, so the same chunk
works whether the target is PDF, HTML or Markdown.

```{r table-md}
regsen_table(res, format = "markdown", digits = 3, max_rows = 6)
```

### LaTeX for a journal

The LaTeX flavour follows the economics convention: `booktabs` rules and
notes inside a `threeparttable`, so the note block sets to the width of
the table rather than the width of the page.

```{r table-tex, results = "asis"}
cat(regsen_table(res, format = "latex", digits = 3, max_rows = 4,
                  caption = "Identified sets for the long-regression coefficient",
                  label = "idset", notes = TRUE, escape = FALSE),
    sep = "\n")
```

`notes = TRUE` writes the note a referee looks for -- which analysis,
which hypothesis, how many observations. Supply a character vector
instead to write your own.

Using it in a manuscript needs one line in the preamble:

```latex
\usepackage{booktabs}
\usepackage{threeparttable}
```

Set `threeparttable = FALSE` if you would rather not, and the notes are
appended as plain `\footnotesize` lines.

### Infinite bounds

An unbounded identified set is a result, not missing data, so it is
rendered rather than blanked: `$+\infty$` in LaTeX, the infinity
character in HTML, `+Inf` in Markdown.

```{r infinite}
regsen_table(res, format = "markdown", digits = 3, max_rows = 8)
```

### Feeding modelsummary

`regsen_tidy()` and `regsen_glance()` speak broom's vocabulary, so
results flow into `modelsummary` and anything else built on it. When
`generics` is installed these are also reachable as `tidy()` and
`glance()`.

```{r tidy}
head(regsen_tidy(res), 4)
regsen_glance(res)
```

`estimate` is the medium-regression coefficient, never a function of the
bounds. Under DMP with `rybar = Inf` the identified set is symmetric
about that coefficient, so a midpoint would agree here and then diverge
for Oster or finite `rybar` -- and it is undefined wherever the set is
unbounded.

