# Getting Started

## Rationale

`{tabstats}` is a lightweight package for displaying data in clean, formatted tables directly in the console. It is mainly designed for developers who wants to display their outputs (preferably in a data frame object), and to make the output readable at a glance, configurable without boilerplate, and friendly to interactive workflows.

The package provides four main functions:

Function | Purpose
--- | ---
`table_default()` | General-purpose data frame table
`table_summary()` | Two-column key-value summary table
`corr_matrix()` | Correlation matrix display
`cross_table()` | Cross tabulation with optional percentages

All functions share a common design philosophy:

1. Styling is controlled via a `style = list(...)` argument that accepts either predefined style strings (e.g. `"blue_bold"`) or plain lambda functions (e.g. `\(x) cli::col_red(x)`).
2. Alignment is controlled via an `align` argument that accepts a single string, a length-2 vector, or a named list.
3. Centering is controlled via `center_table = TRUE`, which automatically pads the output to the middle of your terminal.

## Installation

Install the following package from CRAN:

    install.packages("tabstats")

Or install the development version from GitHub:

    # install.packages("pak")
    pak::pak("joshuamarie/tabstats")
    ## devtools::install_github("joshuamarie/tabstats")

## A Quick Tour

The main API of this package displays the data you wanted to display into a specific format

### `table_default()`

Data frames usually looks like this when displayed:

    head(mtcars[, 1:5], 5)

                       mpg cyl disp  hp drat
    Mazda RX4         21.0   6  160 110 3.90
    Mazda RX4 Wag     21.0   6  160 110 3.90
    Datsun 710        22.8   4  108  93 3.85
    Hornet 4 Drive    21.4   6  258 110 3.08
    Hornet Sportabout 18.7   8  360 175 3.15

With `table_default()`, the data frame is now displayed in an APA-style format, with configurable formatting.

    table_default(head(mtcars[, 1:5], 5))

    ─────────────────────────────────
       mpg    cyl  disp  hp   drat
    ─────────────────────────────────
      21.000   6   160   110  3.900
      21.000   6   160   110  3.900
      22.800   4   108   93   3.850
      21.400   6   258   110  3.080
      18.700   8   360   175  3.150
    ─────────────────────────────────

### `table_summary()`

Another form of `table_default()`, except it is best suitable for displaying summarized data, where it requires 2 columns data frame. The simplest use case is a named summary of values, like model diagnostics or descriptive statistics, where the 1st column is the name of the parameter (statistic) while the 2nd column is the estimate.

    df = data.frame(
        Statistic = c("N", "Mean", "SD", "Min", "Max"),
        Value = c("100", "3.45", "1.20", "1.00", "6.00")
    )

    table_summary(
        df,
        title = "Descriptive Statistics",
        header = TRUE
    )

    Descriptive Statistics
    ----------------------
      Statistic    Value
    ----------------------
      N              100
      Mean          3.45
      SD            1.20
      Min           1.00
      Max           6.00
    ----------------------

The `header` means you still wanted to display the column names from the original `df` data frame, otherwise, no column names are present.

### `corr_matrix()`

A much complex but niche function to display the matrix, specifically designed for correlation matrices. If the `display` is a correlation matrix, typically the output of `cor()`, you can directly pass it.

    corr_matrix(cor(mtcars[, 1:4]), method = "Pearson")

                   Correlation Matrix
    ────────────────────────────────────────────────
      Variable    mpg      cyl      disp      hp
    ────────────────────────────────────────────────
      mpg          1      -0.852   -0.848   -0.776
    ────────────────────────────────────────────────
      cyl        -0.852     1       0.902    0.832
    ────────────────────────────────────────────────
      disp       -0.848    0.902     1       0.791
    ────────────────────────────────────────────────
      hp         -0.776    0.832    0.791     1
    ────────────────────────────────────────────────

But, if the data you wanted to display is not a matrix, but on another form, you’re going to have to configure it by building a custom spec with `new_corr_data()` for full control over which values to appear.

A wild example, assuming you want to display the output from `rstatix::cor_test()`:

    cor_mat =
        iris |>
        rstatix::cor_test(Sepal.Width, Sepal.Length, Petal.Length) |>
        dplyr::mutate(
            var1,
            var2,
            cor = format(cor, digits = 2),
            statistic = format(statistic, digits = 2),
            conf_int = paste0(
                "[",
                format(conf.low, digits = 2),
                ", ",
                format(conf.high, digits = 2),
                "]"
            ),

            .keep = "unused"
        )

    cor_mat |>
        with({
            corr_matrix(
                new_corr_data(
                    var1 = var1,
                    var2 = var2,
                    corr = cor,
                    statistic = statistic,
                    pval = p,
                    conf_int = conf_int
                ),
                title = "Pearson Correlation Matrix"
            )
        })

                          Pearson Correlation Matrix
    ──────────────────────────────────────────────────────────────────────
      Variable         Sepal.Width      Sepal.Length      Petal.Length
    ──────────────────────────────────────────────────────────────────────
      Sepal.Width           1               -0.12             -0.43
                                          -1.4e+00          -5.8e+00
                                            0.152           4.51e-08
                                       [-0.27,  0.044]   [-0.55, -0.288]
    ──────────────────────────────────────────────────────────────────────
      Sepal.Length        -0.12               1                0.87
                        -1.4e+00                             2.2e+01
                          0.152                             1.04e-47
                     [-0.27,  0.044]                     [ 0.83,  0.906]
    ──────────────────────────────────────────────────────────────────────
      Petal.Length        -0.43              0.87               1
                        -5.8e+00           2.2e+01
                        4.51e-08          1.04e-47
                     [-0.55, -0.288]   [ 0.83,  0.906]
    ──────────────────────────────────────────────────────────────────────

### `cross_table()`

Another nice function to display the matrices — contingency tables, to be exact. It has (almost) everything to display the contingency table, including the observed frequencies, expected values, and percentages side by side.

    m = matrix(
        c(10, 20, 30, 40),
        nrow = 2,
        dimnames = list(
            c("A", "B"),
            c("X", "Y")
        )
    )

    cross_table(m, percentage = "all")

    ┌──────────────────────────────────┐
    |      Layout for Cont. Table      |
    ├──────────────────────────────────┤
    |  < Freq > (< Expected Value >)   |
    |        < % by total row >        |
    |      < % by total column >       |
    |       < % by grand total >       |
    └──────────────────────────────────┘

          Cross Tabulation: x by y
    ─────────────────────────────────────
                     y
    ─────────────────────────────────────
      x          X         Y      TOTAL
    ─────────────────────────────────────
      A       10 (12)   30 (28)    40
                25%       75%      40%
                33%       43%
                10%       30%

      B       20 (18)   40 (42)    60
                33%       67%      60%
                67%       57%
                20%       40%
    ─────────────────────────────────────
      TOTAL     30        70       100
                30%       70%
    ─────────────────────────────────────

## Styling Primer

All table functions provides an API to style the table.

1. `table_default()` has 2 parameters: `style_colnames` to style the column names you wanted to design, and `style_columns` if you want to apply the style to the entire column you choose to style. Use `td_style()` to configure the style of the column you choose to style.

2. `table_summary()` has a `style` parameter to configure the style of the specific column you wanted to design. Use `sm_style()` to configure the style of the specific column.

3. `cross_table()` has a `style` parameter to configure the style of the data displayed by the function. Use `ct_style()` to configure the style of the displayed values.

4. `corr_matrix()` has a `style` parameter to configure the style of the values you entered, typically from the `display` argument using `new_corr_data()`. Use `cm_style()` to configure those values you assigned into `new_corr_data()` into the displayed table.

The quickest way to style output is with a named string:

    table_summary(
        df,
        title = "Descriptive Statistics",
        header = TRUE,
        style = sm_style(
            left_col = "blue_bold",
            right_col = "green",
            title = "bold",
            sep = ":  "
        )
    )

    Descriptive Statistics
    -----------------------
      Statistic    Value
    -----------------------
      N         :     100
      Mean      :    3.45
      SD        :    1.20
      Min       :    1.00
      Max       :    6.00
    -----------------------

For full control, pass a lambda instead — it receives the text as its argument:

    table_summary(
        df,
        title = "Descriptive Statistics",
        header = TRUE,
        style = sm_style(
            left_col = \(x) cli::col_red(cli::style_bold(x)),
            right_col = \(x) cli::col_cyan(x),
            title = "bold",
            sep = ":  "
        )
    )

    Descriptive Statistics
    -----------------------
      Statistic    Value
    -----------------------
      N         :     100
      Mean      :    3.45
      SD        :    1.20
      Min       :    1.00
      Max       :    6.00
    -----------------------

Hex codes are also supported:

    table_summary(
        df,
        title = "Descriptive Statistics",
        header = TRUE,
        style = sm_style(
            left_col = function(x) {
                red = cli::make_ansi_style("#BD4444")
                red(cli::style_bold(x))
            },
            right_col = \(x) {
                bluish_color = cli::make_ansi_style("#67A2C5")
                bluish_color(x)
            },
            title = "bold",
            sep = ":  "
        )
    )

    Descriptive Statistics
    -----------------------
      Statistic    Value
    -----------------------
      N         :     100
      Mean      :    3.45
      SD        :    1.20
      Min       :    1.00
      Max       :    6.00
    -----------------------

Supported named style strings:

String | Effect
--- | ---
`"bold"` | Bold text
`"italic"` | Italic text
`"blue"`, `"red"`, `"green"`, `"yellow"` | Foreground colour
`"blue_bold"` | Colour + bold (combinable with `_`)
`"red_italic"` | Colour + italic

More example: Imagine you want to apply for the p-value of the output from `rstatix::cor_test()`, an earlier example. In `corr_matrix()`, you can even conditionally format the specified value from `new_corr_data()`.

    cor_mat |>
        with({
            corr_matrix(
                new_corr_data(
                    var1 = var1,
                    var2 = var2,
                    corr = cor,
                    statistic = statistic,
                    pval = p,
                    conf_int = conf_int
                ),
                title = "Pearson Correlation Matrix",
                style = cm_style(
                    pval = function(x) {
                        x_num = as.numeric(x)
                        if (is.na(x_num) || x_num > 0.05) {
                            cli::style_italic(x)
                        } else if (x_num > 0.01) {
                            reddish = cli::make_ansi_style("#CE2626")
                            reddish(x)
                            # or just cli::col_red(x)
                        } else {
                            cli::style_bold("<0.001")
                        }
                    }
                )
            )
        })

                          Pearson Correlation Matrix
    ──────────────────────────────────────────────────────────────────────
      Variable         Sepal.Width      Sepal.Length      Petal.Length
    ──────────────────────────────────────────────────────────────────────
      Sepal.Width           1               -0.12             -0.43
                                          -1.4e+00          -5.8e+00
                                            0.152            <0.001
                                       [-0.27,  0.044]   [-0.55, -0.288]
    ──────────────────────────────────────────────────────────────────────
      Sepal.Length        -0.12               1                0.87
                        -1.4e+00                             2.2e+01
                          0.152                              <0.001
                     [-0.27,  0.044]                     [ 0.83,  0.906]
    ──────────────────────────────────────────────────────────────────────
      Petal.Length        -0.43              0.87               1
                        -5.8e+00           2.2e+01
                         <0.001            <0.001
                     [-0.55, -0.288]   [ 0.83,  0.906]
    ──────────────────────────────────────────────────────────────────────