Skip to contents

The format set of functions can be combined to format a summarised_result object (see R package omopgenerics) into a nice tibble, flextable or gt table to display in reports and shiny apps.

The functions formatEstimateValue(), formatEstimateName(), formatHeader(), and lastly formatTable() can be implemented in a pipeline to obtain the desired formatted table. Otherwise, these steps are implemented in the function visOmopTable().

Formatting functions in a pipeline

First, we load the relevant libraries and generate a summarised_result with mock results.

1. formatEstimateValue()

This function provides tools to format the estimate_value column: choose number of decimals to display for each estimate_type or estimate_name (decimals), and change change the decimal and thousand/million separator mark (decimalMark and bigMark respectively)

By default, decimals of integer values are set to 0, numeric to 2, percentage to 1, and proportion to 3. The defaulted decimal mark is “.” while the thousand/million separator is “,”.

mock_sr <- mock_sr |> formatEstimateValue()
mock_sr |> glimpse()

If we want the same number of decimals for all the estimates, instead of a named vector the decimal argument can be a numeric pointing the number of decimals.

2. formatEstimateName()

We can customise estimate display by changing the estimate name and joining different estimates in the same row. For instance, we can display counts and percentages together as “N (%)”.

The estimateNameFormat is where combinations can be specified. Values from estimate_name’s column should be specified between <…>. The new estimate_name will be the names of this vector, or the value itself when it is not named.

mock_sr <- mock_sr |> 
  formatEstimateName(
    estimateNameFormat = c(
      "N (%)" = "<count> (<percentage>%)", 
      "N" = "<count>",
      "Mean (SD)" = "<mean> (<sd>)"
    ),
    keepNotFormatted = FALSE,
    useFormatOrder = FALSE
  )
mock_sr |> glimpse()

Additional input arguments are keepNotFormatted to specify whether not formatted rows should be returned or dropped. If useFormatOrder is TRUE, estimates will be presented in the order given in estimateNameFormat, if FALSE, the original order will be kept (where there is more than one estimate, the new position will be the first of the estimates being merged).

3. formatHeader()

This function helps to create a nice header for a flextable or gt table. For instance, instead of having a column specifying the group name and level, we might one them in the header.

Header keys: there are 3 different types of headers, identified with the keys “header”, “header_name”, and “header_level”.

  • header: Header labels passed to header but which are not part of the input table (are not columns names or values).
  • header_name: Header labels that come from column names in the input table.
  • header_level: Header labels that come from values of selected columns in the input table.

For instance, we might want to pivot by “group_level” and have an upper header called “Names of the cohorts”. To do that we would proceed as follows:

mock_sr |>
  formatHeader(
    header = c("Names of the cohorts", "group_level"),
    delim = "\n",
    includeHeaderName = TRUE,
    includeHeaderKey = TRUE
  ) |>
  glimpse()

The label keys can be removed with includeHeaderKey set to FALSE. However, having these keys in our header will allow to style separately the different header types in the next step (fxTable and gtTable). If we wish to remove the header pointing to the column name (group_level), we can set includeHeaderName to FALSE.

Continuing with our example, we want to pivot by strata (name and level), but, we do not want the column names (that is, strata_name and strata_level) to appear in the header:

mock_sr <- mock_sr |>
  mutate(across(c("strata_name", "strata_level"), ~ gsub("&&&", "and", .x))) |>
  formatHeader(
    header = c("Stratifications", "strata_name", "strata_level"),
    delim = "\n",
    includeHeaderName = FALSE,
    includeHeaderKey = TRUE
  ) 

mock_sr |> glimpse()

Notice, how we substitute the keyWord “&&&” to “and”, to get a nice header.

4. gtTable() and fxTable()

Finally, we have the functions gtTable and fxTable which will transform our tibble into a gt or flextable object respectively. These functions provide several tools to personalise the formatted table.

gtTable()

Let’s start by manipulating the dataframe to have the columns that we want to display, and then use gtTable with default values:

# first we select the columns we want:
mock_sr <- mock_sr |>
  splitGroup() |>
  select(!all_of(c(
    "cdm_name", "estimate_type", "result_id","additional_name", 
    "additional_level"
  ))) 
mock_sr |>  gtTable()

Now, we want to group results by “cohort_name”. More specifically we want to have a row which the name of each cohort before the results of that cohort, and that cohort1 comes before cohort2. Additionally, we want to merge those rows what contain the same information for all the columns. To get this table we will use gtTable as follows:

mock_sr |>  
  gtTable(
    groupColumn = "cohort_name",
    groupAsColumn = FALSE,
    groupOrder = c("cohort1", "cohort2"),
    merge = "all_columns"
  )

We might also want to modify the default style of the table. For instance, we might want to highlight the cohort_name labels with a blue background, have the body text in red, and use a combination of orange and yellow for the header. We can do it with the style argument:

mock_sr |>  
  gtTable(
    style = list(
      "header" = list(gt::cell_text(weight = "bold"), 
                      gt::cell_fill(color = "orange")),
      "header_level" = list(gt::cell_text(weight = "bold"), 
                      gt::cell_fill(color = "yellow")),
      "column_name" = gt::cell_text(weight = "bold"),
      "group_label" = list(gt::cell_fill(color = "blue"),
                           gt::cell_text(color = "white", weight = "bold")),
      "body" = gt::cell_text(color = "red")
    ),
    groupColumn = "cohort_name",
    groupAsColumn = FALSE,
    groupOrder = c("cohort1", "cohort2"),
    merge = "all_columns"
  )

fxTable()

To obtain a similar result but with a flextable object, we can use fxTable with the same arguments as before, however, style must be adapted to use the officer package since it is the accepted by flextable.

mock_sr |>  
  fxTable(
    style = list(
      "header" = list(
        "cell" = officer::fp_cell(background.color = "orange"),
        "text" = officer::fp_text(bold = TRUE)),
      "header_level" = list(
        "cell" = officer::fp_cell(background.color = "yellow"),
        "text" = officer::fp_text(bold = TRUE)),
      "column_name" = list("text" = officer::fp_text(bold = TRUE)),
      "group_label" = list(
        "cell" = officer::fp_cell(background.color = "blue"),
        "text" = officer::fp_text(bold = TRUE, color = "white")),
      "body" = list("text" = officer::fp_text(color = "red"))
    ),
    groupColumn = "cohort_name",
    groupAsColumn = FALSE,
    groupOrder = c("cohort1", "cohort2"),
    merge = "all_columns"
  )

visOmopTable(): all at once

This function wraps the tools seen so far to format a summarised result at once. While it is convenient to have it all in one function, the level of table manipulation allowed is less than with the pipeline.

First, we create a new mock summarised result:

mock_sr2 <- mockSummarisedResult()

For instance, if we want to have a flextable with strata as header, we will write “strata” in header instead of strata_name and strata_level. Same as before, we can input header keys (e.g. “Stratifications” in the example below).

The split argument points to which name-level columns to split (group, strata and/or additional). Refer to the vignette split and unite for further information on this functionality.

mock_sr2 |> visOmopTable(
  formatEstimateName = c("N%" = "<count> (<percentage>)",
                         "N" = "<count>",
                         "Mean (SD)" = "<mean> (<sd>)"),
  header = c("Stratifications", "strata")
)

By default, it returns a gt table, but it can be changed to “flextable” and “tibble” in the type argument.

The groupColumn can be used to create groups in the table body. For instance, looking at the previous table, we might want to group by cohort name:

mock_sr2 |> visOmopTable(
  formatEstimateName = c("N%" = "<count> (<percentage>)",
                         "N" = "<count>",
                         "Mean (SD)" = "<mean> (<sd>)"),
  header = c("Stratifications", "strata"),
  split = c("group","additional"),
  groupColumn = "cohort_name"
)

Additional options can be specified in the .options argument. These options are taken from the other format functions and gt/fx table functions seen before. To see a list of allowed arguments and their default values use optionsTable():