Code
# Check what columns exist
names(your_data)
# Common mistake: using wrong case
forest_plot(data, point = "HR", ...) # Wrong: "HR"
forest_plot(data, point = "hr", ...) # Correct: "hr"This guide covers common issues and their solutions when using tabviz.
When something isn’t working, check:
scale = "log" with non-positive values?Symptom: Error message about missing column.
Cause: Column name typo or the column doesn’t exist.
Solution:
Symptom: Rows appear without intervals or with missing values.
Cause: Columns contain NA values or wrong data types.
Solution:
Symptom: Hierarchical groups appear flat or have wrong nesting.
Cause: Group column contains unexpected values or ID collisions.
Solution:
Symptom: Header rows show intervals, or data rows appear as headers.
Cause: row_type column has incorrect values.
Solution:
# Valid row_type values
valid_types <- c("header", "data", "summary", "spacer")
# Check your values
your_data |>
count(row_type)
# Ensure header/spacer rows have NA for estimates
your_data <- your_data |>
mutate(
hr = if_else(row_type %in% c("header", "spacer"), NA_real_, hr),
lower = if_else(row_type %in% c("header", "spacer"), NA_real_, lower),
upper = if_else(row_type %in% c("header", "spacer"), NA_real_, upper)
)Symptom: Error or unexpected axis range when using scale = "log".
Cause: Data contains zero or negative values, which are undefined on log scale.
Solution:
Symptom: Data points are compressed into a small portion of the axis.
Cause: Outliers or automatic axis calculation including extreme values.
Solution:
# Check data range
range(your_data$hr, na.rm = TRUE)
range(your_data$lower, na.rm = TRUE)
range(your_data$upper, na.rm = TRUE)
# Option 1: Override axis range
forest_plot(your_data, ...,
axis_range = c(0.5, 2.0) # Focus on relevant range
)
# Option 2: Filter outliers
filtered <- your_data |>
filter(between(hr, 0.3, 3))Symptom: Confidence intervals extend beyond axis bounds.
Cause: Manual axis range doesn’t accommodate all data.
Solution:
# Find the actual data extent
min_val <- min(your_data$lower, na.rm = TRUE)
max_val <- max(your_data$upper, na.rm = TRUE)
message("Data range: ", round(min_val, 2), " to ", round(max_val, 2))
# Adjust axis_range to include all data
forest_plot(your_data, ...,
axis_range = c(min_val * 0.9, max_val * 1.1)
)Symptom: Axis shows but has no tick marks or unexpected tick positions.
Solution:
Symptom: Error when calling save_plot(): “Package V8 is required”
Solution:
Symptom: PDF/PNG export fails with rsvg errors.
Solution:
Symptom: Export fails with message about missing JS file.
Cause: Package installation is incomplete.
Solution:
Symptom: Exported SVG/PNG has different colors than the interactive widget.
Cause: Theme not applied consistently to both.
Solution:
Symptom: Plot doesn’t appear in RStudio’s Viewer pane.
Cause: Viewer pane size or rendering issues.
Solution:
Symptom: Plot is too small, cut off, or doesn’t fill container.
Solution:
Symptom: forestProxy() calls don’t update the plot.
Cause: Proxy created outside reactive context.
Solution:
Symptom: Bold, color, or other styles don’t appear.
Cause: Passing values directly instead of column names.
Solution:
# Wrong: passing values directly
col_numeric("hr", bold = TRUE, color = "#ff0000")
# Correct: passing column names that contain the values
col_numeric("hr", bold = "is_bold", color = "hr_color")
# The data must have these columns:
data <- data |>
mutate(
is_bold = pval < 0.05,
hr_color = if_else(hr < 1, "#16a34a", "#dc2626")
)Symptom: Text appears in wrong font.
Cause: Custom font not available on system.
Solution:
<tabviz::WebSpec>
@ data :'data.frame': 2 obs. of 3 variables:
.. $ study: chr "A" "B"
.. $ hr : num 0.8 1.2
.. $ n : num 100 200
@ label_col : chr "study"
@ label_header : chr "Study"
@ group_col : chr NA
@ group_cols : chr(0)
@ columns :List of 2
.. $ : <tabviz::ColumnSpec>
.. ..@ id : chr "hr"
.. ..@ header : chr "HR"
.. ..@ field : chr "hr"
.. ..@ type : chr "numeric"
.. ..@ width : chr "auto"
.. ..@ align : chr "left"
.. ..@ header_align : chr "left"
.. ..@ wrap : logi FALSE
.. ..@ sortable : logi TRUE
.. ..@ options :List of 1
.. .. .. $ numeric:List of 4
.. .. .. ..$ decimals : num 2
.. .. .. ..$ digits : NULL
.. .. .. ..$ thousandsSep: logi FALSE
.. .. .. ..$ abbreviate : logi FALSE
.. ..@ style_bold : chr NA
.. ..@ style_italic : chr NA
.. ..@ style_color : chr NA
.. ..@ style_bg : chr NA
.. ..@ style_badge : chr NA
.. ..@ style_icon : chr NA
.. ..@ style_emphasis: chr NA
.. ..@ style_muted : chr NA
.. ..@ style_accent : chr NA
.. $ : <tabviz::ColumnSpec>
.. ..@ id : chr "n"
.. ..@ header : chr "N"
.. ..@ field : chr "n"
.. ..@ type : chr "numeric"
.. ..@ width : chr "auto"
.. ..@ align : chr "left"
.. ..@ header_align : chr "left"
.. ..@ wrap : logi FALSE
.. ..@ sortable : logi TRUE
.. ..@ options :List of 1
.. .. .. $ numeric:List of 4
.. .. .. ..$ decimals : num 0
.. .. .. ..$ digits : NULL
.. .. .. ..$ thousandsSep: chr ","
.. .. .. ..$ abbreviate : logi FALSE
.. ..@ style_bold : chr NA
.. ..@ style_italic : chr NA
.. ..@ style_color : chr NA
.. ..@ style_bg : chr NA
.. ..@ style_badge : chr NA
.. ..@ style_icon : chr NA
.. ..@ style_emphasis: chr NA
.. ..@ style_muted : chr NA
.. ..@ style_accent : chr NA
@ groups : list()
@ summaries : list()
@ overall_summary : <tabviz::GroupSummary>
.. @ group_id: chr(0)
.. @ point : int(0)
.. @ lower : int(0)
.. @ upper : int(0)
.. @ metadata: list()
@ theme : <tabviz::WebTheme>
.. @ name : chr "default"
.. @ colors : <tabviz::ColorPalette>
.. .. @ background : chr "#ffffff"
.. .. @ foreground : chr "#333333"
.. .. @ primary : chr "#0891b2"
.. .. @ secondary : chr "#64748b"
.. .. @ accent : chr "#8b5cf6"
.. .. @ muted : chr "#94a3b8"
.. .. @ border : chr "#e2e8f0"
.. .. @ row_bg : chr "#ffffff"
.. .. @ alt_bg : chr "#f8fafc"
.. .. @ interval : chr "#0891b2"
.. .. @ interval_line : chr "#475569"
.. .. @ interval_positive: chr "#0891b2"
.. .. @ interval_negative: chr "#dc2626"
.. .. @ interval_neutral : chr "#64748b"
.. .. @ summary_fill : chr "#0891b2"
.. .. @ summary_border : chr "#0e7490"
.. @ typography : <tabviz::Typography>
.. .. @ font_family : chr "system-ui, -apple-system, sans-serif"
.. .. @ font_size_sm : chr "0.75rem"
.. .. @ font_size_base : chr "0.875rem"
.. .. @ font_size_lg : chr "1rem"
.. .. @ font_weight_normal: num 400
.. .. @ font_weight_medium: num 500
.. .. @ font_weight_bold : num 600
.. .. @ line_height : num 1.5
.. .. @ header_font_scale : num 1.05
.. @ spacing : <tabviz::Spacing>
.. .. @ row_height : num 24
.. .. @ header_height : num 32
.. .. @ section_gap : num 16
.. .. @ padding : num 12
.. .. @ container_padding: num 0
.. .. @ axis_gap : num 12
.. .. @ group_padding : num 8
.. .. @ cell_padding_x : num 10
.. .. @ cell_padding_y : num 4
.. .. @ column_gap : num 8
.. @ shapes : <tabviz::Shapes>
.. .. @ point_size : num 6
.. .. @ summary_height: num 10
.. .. @ line_width : num 1.5
.. .. @ border_radius : num 2
.. .. @ effect_colors : chr [1:5] "#0891b2" "#16a34a" "#f59e0b" "#ef4444" "#8b5cf6"
.. .. @ marker_shapes : chr [1:4] "square" "circle" "diamond" "triangle"
.. @ axis : <tabviz::AxisConfig>
.. .. @ range_min : num NA
.. .. @ range_max : num NA
.. .. @ tick_count : num NA
.. .. @ tick_values : NULL
.. .. @ gridlines : logi FALSE
.. .. @ gridline_style: chr "dotted"
.. .. @ ci_clip_factor: num 2
.. .. @ include_null : logi TRUE
.. .. @ symmetric : NULL
.. .. @ null_tick : logi TRUE
.. .. @ marker_margin : logi TRUE
.. @ layout : <tabviz::LayoutConfig>
.. .. @ plot_position : chr "right"
.. .. @ table_width : chr "auto"
.. .. @ plot_width : chr "auto"
.. .. @ container_border : logi FALSE
.. .. @ container_border_radius: num 8
.. .. @ banding : logi TRUE
.. @ group_headers: <tabviz::GroupHeaderStyles>
.. .. @ level1_font_size : chr "0.9375rem"
.. .. @ level1_font_weight : num 600
.. .. @ level1_italic : logi FALSE
.. .. @ level1_background : NULL
.. .. @ level1_border_bottom: logi FALSE
.. .. @ level2_font_size : chr "0.875rem"
.. .. @ level2_font_weight : num 500
.. .. @ level2_italic : logi FALSE
.. .. @ level2_background : NULL
.. .. @ level2_border_bottom: logi FALSE
.. .. @ level3_font_size : chr "0.875rem"
.. .. @ level3_font_weight : num 400
.. .. @ level3_italic : logi FALSE
.. .. @ level3_background : NULL
.. .. @ level3_border_bottom: logi FALSE
.. .. @ indent_per_level : num 16
@ interaction : <tabviz::InteractionSpec>
.. @ show_filters : logi FALSE
.. @ show_legend : logi TRUE
.. @ enable_sort : logi TRUE
.. @ enable_collapse: logi TRUE
.. @ enable_select : logi TRUE
.. @ enable_hover : logi TRUE
.. @ enable_resize : logi TRUE
.. @ enable_export : logi TRUE
.. @ tooltip_fields : NULL
.. @ enable_themes : chr "default"
@ labels : NULL
@ row_bold_col : chr NA
@ row_italic_col : chr NA
@ row_color_col : chr NA
@ row_bg_col : chr NA
@ row_badge_col : chr NA
@ row_icon_col : chr NA
@ row_indent_col : chr NA
@ row_type_col : chr NA
@ row_emphasis_col : chr NA
@ row_muted_col : chr NA
@ row_accent_col : chr NA
@ marker_color_col : chr NA
@ marker_shape_col : chr NA
@ marker_opacity_col: chr NA
@ marker_size_col : chr NA
@ weight_col : chr NA
study hr n
1 A 0.8 100
2 B 1.2 200
[[1]]
<tabviz::ColumnSpec>
@ id : chr "hr"
@ header : chr "HR"
@ field : chr "hr"
@ type : chr "numeric"
@ width : chr "auto"
@ align : chr "left"
@ header_align : chr "left"
@ wrap : logi FALSE
@ sortable : logi TRUE
@ options :List of 1
.. $ numeric:List of 4
.. ..$ decimals : num 2
.. ..$ digits : NULL
.. ..$ thousandsSep: logi FALSE
.. ..$ abbreviate : logi FALSE
@ style_bold : chr NA
@ style_italic : chr NA
@ style_color : chr NA
@ style_bg : chr NA
@ style_badge : chr NA
@ style_icon : chr NA
@ style_emphasis: chr NA
@ style_muted : chr NA
@ style_accent : chr NA
[[2]]
<tabviz::ColumnSpec>
@ id : chr "n"
@ header : chr "N"
@ field : chr "n"
@ type : chr "numeric"
@ width : chr "auto"
@ align : chr "left"
@ header_align : chr "left"
@ wrap : logi FALSE
@ sortable : logi TRUE
@ options :List of 1
.. $ numeric:List of 4
.. ..$ decimals : num 0
.. ..$ digits : NULL
.. ..$ thousandsSep: chr ","
.. ..$ abbreviate : logi FALSE
@ style_bold : chr NA
@ style_italic : chr NA
@ style_color : chr NA
@ style_bg : chr NA
@ style_badge : chr NA
@ style_icon : chr NA
@ style_emphasis: chr NA
@ style_muted : chr NA
@ style_accent : chr NA
[1] "default"
For debugging interactive widgets:
When reporting issues, create a minimal example:
# Minimal data that reproduces the problem
test_data <- data.frame(
study = c("Test 1", "Test 2"),
hr = c(0.8, 1.2),
lower = c(0.6, 0.9),
upper = c(1.1, 1.6)
)
# Minimal code
forest_plot(test_data,
point = "hr", lower = "lower", upper = "upper",
label = "study"
)
# Include session info
sessionInfo()If you’ve tried the above and still have issues:
sessionInfo() output---
title: "Troubleshooting"
---
```{r}
#| include: false
library(tabviz)
library(dplyr)
```
This guide covers common issues and their solutions when using tabviz.
## Quick Diagnostic Checklist
When something isn't working, check:
1. **Column names** - Are they spelled correctly and exist in the data?
2. **Data types** - Are numeric columns actually numeric?
3. **NAs** - Are there unexpected missing values?
4. **Scale** - Using `scale = "log"` with non-positive values?
5. **Dependencies** - Is V8 installed for exports?
## Data Issues
### "Column not found in data"
**Symptom:** Error message about missing column.
**Cause:** Column name typo or the column doesn't exist.
**Solution:**
```{r}
#| eval: false
# Check what columns exist
names(your_data)
# Common mistake: using wrong case
forest_plot(data, point = "HR", ...) # Wrong: "HR"
forest_plot(data, point = "hr", ...) # Correct: "hr"
```
### Unexpected NAs in Plot
**Symptom:** Rows appear without intervals or with missing values.
**Cause:** Columns contain NA values or wrong data types.
**Solution:**
```{r}
#| eval: false
# Check for NAs
summary(your_data)
# Check column types - character columns won't work for numeric fields
sapply(your_data, class)
# Fix character columns that should be numeric
your_data$hr <- as.numeric(your_data$hr)
```
### Groups Not Displaying Correctly
**Symptom:** Hierarchical groups appear flat or have wrong nesting.
**Cause:** Group column contains unexpected values or ID collisions.
**Solution:**
```{r}
#| eval: false
# Check unique group values
table(your_data$region)
table(your_data$subregion)
# Ensure nested groups have consistent parent values
your_data |>
group_by(region, subregion) |>
count()
```
### Data Rows Mixed with Headers
**Symptom:** Header rows show intervals, or data rows appear as headers.
**Cause:** `row_type` column has incorrect values.
**Solution:**
```{r}
#| eval: false
# Valid row_type values
valid_types <- c("header", "data", "summary", "spacer")
# Check your values
your_data |>
count(row_type)
# Ensure header/spacer rows have NA for estimates
your_data <- your_data |>
mutate(
hr = if_else(row_type %in% c("header", "spacer"), NA_real_, hr),
lower = if_else(row_type %in% c("header", "spacer"), NA_real_, lower),
upper = if_else(row_type %in% c("header", "spacer"), NA_real_, upper)
)
```
## Scale and Axis Issues
### Log Scale with Non-Positive Values
**Symptom:** Error or unexpected axis range when using `scale = "log"`.
**Cause:** Data contains zero or negative values, which are undefined on log scale.
**Solution:**
```{r}
#| eval: false
# Find problematic rows
your_data |>
filter(hr <= 0 | lower <= 0 | upper <= 0)
# Option 1: Filter out invalid rows
valid_data <- your_data |>
filter(hr > 0, lower > 0, upper > 0)
# Option 2: Use linear scale instead
forest_plot(your_data, ..., scale = "linear", null_value = 0)
```
### Axis Range Too Wide
**Symptom:** Data points are compressed into a small portion of the axis.
**Cause:** Outliers or automatic axis calculation including extreme values.
**Solution:**
```{r}
#| eval: false
# Check data range
range(your_data$hr, na.rm = TRUE)
range(your_data$lower, na.rm = TRUE)
range(your_data$upper, na.rm = TRUE)
# Option 1: Override axis range
forest_plot(your_data, ...,
axis_range = c(0.5, 2.0) # Focus on relevant range
)
# Option 2: Filter outliers
filtered <- your_data |>
filter(between(hr, 0.3, 3))
```
### Axis Range Too Narrow
**Symptom:** Confidence intervals extend beyond axis bounds.
**Cause:** Manual axis range doesn't accommodate all data.
**Solution:**
```{r}
#| eval: false
# Find the actual data extent
min_val <- min(your_data$lower, na.rm = TRUE)
max_val <- max(your_data$upper, na.rm = TRUE)
message("Data range: ", round(min_val, 2), " to ", round(max_val, 2))
# Adjust axis_range to include all data
forest_plot(your_data, ...,
axis_range = c(min_val * 0.9, max_val * 1.1)
)
```
### Tick Marks Not Appearing
**Symptom:** Axis shows but has no tick marks or unexpected tick positions.
**Solution:**
```{r}
#| eval: false
# Specify explicit tick positions
forest_plot(your_data, ...,
scale = "log",
axis_ticks = c(0.5, 0.7, 1, 1.5, 2) # Explicit ticks
)
# Or use theme settings
forest_plot(your_data, ...,
theme = web_theme_default() |>
set_axis(tick_count = 5, gridlines = TRUE)
)
```
## Export Failures
### V8 Not Installed
**Symptom:** Error when calling `save_plot()`: "Package V8 is required"
**Solution:**
```{r}
#| eval: false
# Install V8
install.packages("V8")
# On some systems, you may need system libraries first:
# macOS: brew install v8
# Ubuntu: sudo apt-get install libv8-dev
```
### rsvg Issues
**Symptom:** PDF/PNG export fails with rsvg errors.
**Solution:**
```{r}
#| eval: false
# Install rsvg
install.packages("rsvg")
# On macOS, you may need:
# brew install librsvg
# On Ubuntu:
# sudo apt-get install librsvg2-dev
```
### "SVG generator JavaScript file not found"
**Symptom:** Export fails with message about missing JS file.
**Cause:** Package installation is incomplete.
**Solution:**
```{r}
#| eval: false
# Reinstall the package
pak::pak("kaskarn/tabviz", force = TRUE)
# Verify installation
system.file("js/svg-generator.js", package = "tabviz")
# Should return a path, not ""
```
### Colors Differ Between Display and Export
**Symptom:** Exported SVG/PNG has different colors than the interactive widget.
**Cause:** Theme not applied consistently to both.
**Solution:**
```{r}
#| eval: false
# Use the same theme for display and export
my_theme <- web_theme_lancet()
# Interactive
forest_plot(data, ..., theme = my_theme)
# Export
spec <- web_spec(data, ..., theme = my_theme)
save_plot(spec, "output.svg")
```
## Widget Rendering Issues
### Blank Output in RStudio Viewer
**Symptom:** Plot doesn't appear in RStudio's Viewer pane.
**Cause:** Viewer pane size or rendering issues.
**Solution:**
```{r}
#| eval: false
# Try in browser instead
plot <- forest_plot(your_data, ...)
htmltools::browsable(plot)
# Or save to file and open
htmlwidgets::saveWidget(plot, "temp.html")
browseURL("temp.html")
```
### Widget Not Sizing Correctly
**Symptom:** Plot is too small, cut off, or doesn't fill container.
**Solution:**
```{r}
#| eval: false
# Specify explicit dimensions
forest_plot(your_data, ...,
width = 900,
height = 600
)
# For Shiny, use CSS units
forestOutput("plot", width = "100%", height = "600px")
```
### Shiny: Proxy Not Working
**Symptom:** `forestProxy()` calls don't update the plot.
**Cause:** Proxy created outside reactive context.
**Solution:**
```{r}
#| eval: false
# Wrong: proxy at top level
# proxy <- forestProxy("forest") # This will fail!
# Correct: proxy inside reactive context
observeEvent(input$button, {
proxy <- forestProxy("forest")
forest_sort(proxy, "hr", "asc")
})
```
## Theme and Styling Issues
### Styles Not Applying
**Symptom:** Bold, color, or other styles don't appear.
**Cause:** Passing values directly instead of column names.
**Solution:**
```{r}
#| eval: false
# Wrong: passing values directly
col_numeric("hr", bold = TRUE, color = "#ff0000")
# Correct: passing column names that contain the values
col_numeric("hr", bold = "is_bold", color = "hr_color")
# The data must have these columns:
data <- data |>
mutate(
is_bold = pval < 0.05,
hr_color = if_else(hr < 1, "#16a34a", "#dc2626")
)
```
### Font Not Loading
**Symptom:** Text appears in wrong font.
**Cause:** Custom font not available on system.
**Solution:**
```{r}
#| eval: false
# Use web-safe fallback fonts
web_theme_default() |>
set_typography(
font_family = "Georgia, 'Times New Roman', serif"
)
# For exports, fonts must be installed on the rendering system
```
## Debug Patterns
### Inspecting WebSpec
```{r}
# Create spec without rendering (table-only spec)
spec <- web_spec(
data.frame(
study = c("A", "B"),
hr = c(0.8, 1.2),
n = c(100, 200)
),
label = "study",
columns = list(
col_numeric("hr", "HR"),
col_n("n")
)
)
# Print summary
print(spec)
# Access components
spec@data
spec@columns
spec@theme@name
```
### Check Export Output
```{r}
#| eval: false
# Generate SVG and check structure
save_plot(spec, "debug.svg")
# Read and inspect the SVG
svg_content <- readLines("debug.svg")
head(svg_content, 20)
```
### Browser Developer Tools
For debugging interactive widgets:
1. Right-click the widget → "Inspect"
2. Check Console tab for JavaScript errors
3. Check Elements tab for DOM structure
4. Check Network tab for failed resources
### Minimal Reproducible Example
When reporting issues, create a minimal example:
```{r}
#| eval: false
# Minimal data that reproduces the problem
test_data <- data.frame(
study = c("Test 1", "Test 2"),
hr = c(0.8, 1.2),
lower = c(0.6, 0.9),
upper = c(1.1, 1.6)
)
# Minimal code
forest_plot(test_data,
point = "hr", lower = "lower", upper = "upper",
label = "study"
)
# Include session info
sessionInfo()
```
## Getting Help
If you've tried the above and still have issues:
1. Check [GitHub Issues](https://github.com/kaskarn/tabviz/issues) for similar problems
2. Create a minimal reproducible example
3. Include `sessionInfo()` output
4. Open a new issue with your example and session info