---
title: "Row Styling"
---
```{r}
#| include: false
library(tabviz)
library(dplyr)
```
Control the visual appearance of individual rows using `row_*` parameters. This gives you precise control over text styling, indentation, colors, and badges—essential for creating publication-ready meta-analysis figures.
## Text Styling
Control text appearance with `row_bold`, `row_italic`, and `row_color`:
```{r}
# Use glp1_trials which has pre-computed row_bold
data(glp1_trials)
text_demo <- glp1_trials |>
filter(group == "Main Trials", row_type == "data") |>
head(4) |>
mutate(
ritalic = !row_bold,
rcolor = ifelse(row_bold, "#0369a1", "#64748b")
)
tabviz(text_demo,
label = "study",
columns = list(
col_text("drug", "Drug"),
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
),
row_bold = "row_bold",
row_italic = "ritalic",
row_color = "rcolor"
)
```
---
## Indentation
Create visual hierarchy with `row_indent`. Values represent nesting levels (0, 1, 2, ...):
```{r}
indent_demo <- data.frame(
label = c(
"All Patients",
" Age < 65",
" Male", " Female",
" Age >= 65",
" Male", " Female"
),
hr = c(0.78, 0.72, 0.70, 0.75, 0.85, 0.82, 0.88),
lower = c(0.68, 0.58, 0.54, 0.60, 0.72, 0.66, 0.72),
upper = c(0.89, 0.89, 0.91, 0.94, 1.00, 1.02, 1.08),
rindent = c(0, 1, 2, 2, 1, 2, 2),
rbold = c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE)
)
tabviz(indent_demo,
label = "label",
columns = list(
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
),
row_indent = "rindent",
row_bold = "rbold",
theme = web_theme_modern()
)
```
---
## Badges
Add small labels to highlight specific rows with `row_badge`:
```{r}
# nba_efficiency has an 'award' column perfect for badges
data(nba_efficiency)
nba_efficiency |>
filter(conference == "East") |>
head(6) |>
tabviz(
label = "player",
columns = list(
col_text("team", "Team", width = 60),
col_numeric("ppg", "PPG"),
viz_forest(point = "per", lower = "per_lower", upper = "per_upper",
null_value = 15, axis_label = "PER")
),
row_badge = "award",
row_bold = "all_star",
theme = web_theme_modern()
)
```
Badges are useful for marking awards, flagging key results, or indicating data quality.
::: {.callout-tip}
## See Also
For more examples with badge data, see [Package Data](package-data.qmd#nba_efficiency).
:::
---
## Background Colors
Highlight rows with `row_bg` for background colors:
```{r}
#| eval: false
tabviz(data,
label = "label",
columns = list(
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
),
row_bg = "background_color" # Column with hex colors like "#f0f9ff"
)
```
Use sparingly—subtle tints work best.
---
## Semantic Styling
For theme-aware styling that adapts automatically when you change themes, use semantic shortcuts:
| Parameter | Effect |
|-----------|--------|
| `row_emphasis` | Bold text + theme primary color (for key results) |
| `row_muted` | Lighter color, reduced prominence (for secondary data) |
| `row_accent` | Theme accent color (for highlighted findings) |
```{r}
#| eval: false
tabviz(data,
label = "label",
columns = list(
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
),
row_emphasis = "is_primary", # Column with TRUE/FALSE
row_muted = "is_secondary" # Column with TRUE/FALSE
)
```
These adapt automatically to any theme, so you don't need to update color values when switching from `web_theme_jama()` to `web_theme_lancet()`.
---
## Expression-Based Styling
Instead of creating style columns in your data, you can use formula expressions that are evaluated on the fly. This is especially useful for conditional styling based on data values:
```{r}
expr_demo <- data.frame(
study = c("Alpha 2020", "Beta 2021", "Gamma 2022", "Delta 2023"),
hr = c(0.72, 0.85, 0.91, 0.68),
lower = c(0.55, 0.70, 0.75, 0.52),
upper = c(0.95, 1.03, 1.10, 0.89),
pval = c(0.01, 0.1, 0.3, 0.005)
)
tabviz(expr_demo,
label = "study",
columns = list(
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
),
# Formula expressions - no need for pre-computed columns
row_bold = ~ pval < 0.05,
row_color = ~ ifelse(pval < 0.05, "#166534", "#64748b"),
title = "Expression-Based Styling",
subtitle = "Bold + green color for significant results (p < 0.05)"
)
```
### How It Works
- Use the tilde (`~`) to start a formula expression
- The expression is evaluated against your data frame
- All column names in your data are available in the expression
- Results should be logical (`TRUE`/`FALSE`) for boolean styles, or strings for colors
### Multiple Conditions
Combine conditions using `&` (and) or `|` (or):
```{r}
#| eval: false
# Bold if significant AND large effect
row_bold = ~ pval < 0.05 & hr < 0.8
# Emphasize if significant OR key study
row_emphasis = ~ pval < 0.05 | is_primary
# Color based on effect direction and significance
row_color = ~ case_when(
hr < 1 & pval < 0.05 ~ "#166534", # Significant benefit - green
hr > 1 & pval < 0.05 ~ "#dc2626", # Significant harm - red
TRUE ~ "#64748b" # Non-significant - gray
)
```
::: {.callout-tip}
## When to Use Expressions vs Columns
**Use formulas** when:
- Styling is based on simple conditions (`pval < 0.05`)
- You want concise, readable code
- Style logic is tightly coupled to the visualization
**Use columns** when:
- Style values are pre-computed or loaded from data
- Same styling is reused across multiple plots
- Complex logic is better computed separately
:::
---
## Row Types
The `row_type` parameter controls fundamental row behavior. This is a manual approach for creating structured layouts with headers, summaries, and spacers—useful when you need precise control over the document structure.
| Type | Behavior | Marker |
|------|----------|--------|
| `"data"` | Standard data row | Point with CI line |
| `"header"` | Section header, spans full width | None |
| `"summary"` | Pooled/subtotal row | Diamond shape |
| `"spacer"` | Empty row for separation | None |
```{r}
# glp1_trials has pre-computed row_type column
glp1_trials |>
filter(group == "Main Trials") |>
head(5) |>
tabviz(
label = "study",
columns = list(
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
),
row_type = "row_type"
)
```
::: {.callout-important}
## NA Values for Non-Data Rows
Rows with `row_type = "header"` or `"spacer"` should have `NA` for `point`, `lower`, and `upper`. Summary rows need valid values to display the diamond.
:::
::: {.callout-tip}
## Row Types vs Row Groups
For automatic grouping based on a column in your data, consider using the `group` parameter instead—it creates collapsible sections without manually specifying row types. See [Row Groups](row-groups.qmd).
:::
::: {.callout-note}
## Built-in Dataset
The `glp1_trials` dataset includes pre-computed `row_type` and `row_bold` columns. See [Package Data](package-data.qmd#glp1_trials) for details.
:::
---
## Complete Example: Meta-Analysis Figure
Here's a publication-ready meta-analysis combining all row styling features:
```{r}
meta_analysis <- data.frame(
label = c(
"Cardiovascular Outcomes",
" EMPA-REG 2015", " CANVAS 2017", " DECLARE 2019", " Subtotal", "",
"Renal Outcomes",
" CREDENCE 2019", " DAPA-CKD 2020", " Subtotal", "",
"Overall"
),
hr = c(NA, 0.86, 0.86, 0.93, 0.88, NA, NA, 0.70, 0.61, 0.66, NA, 0.78),
lower = c(NA, 0.74, 0.75, 0.84, 0.82, NA, NA, 0.59, 0.51, 0.57, NA, 0.73),
upper = c(NA, 0.99, 0.97, 1.03, 0.95, NA, NA, 0.82, 0.72, 0.76, NA, 0.84),
n = c(NA, 7020, 10142, 17160, 34322, NA, NA, 4401, 4304, 8705, NA, 43027),
rtype = c(
"header", "data", "data", "data", "summary", "spacer",
"header", "data", "data", "summary", "spacer", "summary"
),
rbold = c(TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE),
rindent = c(0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0),
rcolor = c("#0369a1", NA, NA, NA, "#0369a1", NA, "#0369a1", NA, NA, "#0369a1", NA, "#166534"),
rbadge = c(NA, NA, NA, NA, "n=3", NA, NA, NA, NA, "n=2", NA, "n=5")
)
tabviz(meta_analysis,
label = "label",
columns = list(
col_numeric("n", "N"),
col_interval("HR (95% CI)", point = "hr", lower = "lower", upper = "upper"),
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log", axis_label = "Hazard Ratio (95% CI)")
),
row_type = "rtype",
row_bold = "rbold",
row_indent = "rindent",
row_color = "rcolor",
row_badge = "rbadge",
theme = web_theme_modern(),
title = "SGLT2 Inhibitors Meta-Analysis",
subtitle = "Cardiovascular and renal outcomes"
)
```
---
## Fluent API Alternative
You can also apply row styling using `set_row_style()` for pipe-based workflows:
```{r}
#| eval: false
tabviz(data,
label = "label",
columns = list(
viz_forest(point = "hr", lower = "lower", upper = "upper",
null_value = 1, scale = "log")
)
) |>
set_row_style(
type = "rtype",
bold = "rbold",
indent = "rindent",
color = "rcolor",
badge = "rbadge"
)
```
This is useful when building styling programmatically or creating multiple variants from a base plot. See [The Fluent API](fluent-api.qmd) for more patterns.
---
## Parameter Reference
All `row_*` parameters accept either a **column name** (string) or a **formula expression** (`~ ...`).
| Parameter | Column Contains | Description |
|-----------|-----------------|-------------|
| `row_bold` | `TRUE`/`FALSE` | Bold text |
| `row_italic` | `TRUE`/`FALSE` | Italic text |
| `row_color` | CSS color (e.g., `"#1a365d"`) | Text color |
| `row_bg` | CSS color | Background color |
| `row_indent` | Integer (0, 1, 2, ...) | Indentation level |
| `row_badge` | Text | Badge label |
| `row_icon` | Emoji/unicode | Icon before label |
| `row_emphasis` | `TRUE`/`FALSE` | Theme-aware emphasis styling |
| `row_muted` | `TRUE`/`FALSE` | Theme-aware muted styling |
| `row_accent` | `TRUE`/`FALSE` | Theme-aware accent styling |
| `row_type` | `"data"`, `"header"`, `"summary"`, `"spacer"` | Row behavior and marker type |
::: {.callout-note}
## Formula Examples
```r
# Using column name
row_bold = "is_significant"
# Using formula expression
row_bold = ~ pval < 0.05
```
:::
---
## See Also
- [Row Groups](row-groups.qmd) — Automatic collapsible sections from column values
- [Styling Functions](../reference/styling.qmd) — Complete `set_row_style()` reference
- [forest_plot()](../reference/tabviz.qmd) — All arguments