omopy.vis¶
Visualization and formatting for OMOP CDM summarised results — format
estimates, render tables, and create plots from SummarisedResult objects.
This module is the Python equivalent of the R visOmopResults package.
Table rendering uses great_tables;
plot rendering uses plotly.
Format Pipeline¶
Composable functions for transforming summarised results into display-ready data.
The typical pipeline is:
format_estimate_value → format_estimate_name → format_header → format_table.
format_estimate_value
¶
format_estimate_value(
result: SummarisedResult,
*,
decimals: dict[str, int] | None = None,
decimal_mark: str = ".",
big_mark: str = ",",
) -> SummarisedResult
Format numeric precision of estimate_value based on estimate_type.
For each row, rounds the value to the number of decimal places
specified by the row's estimate_type and applies decimal/big marks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult
|
A :class: |
required |
decimals
|
dict[str, int] | None
|
Mapping of estimate_type -> number of decimals.
Defaults to |
None
|
decimal_mark
|
str
|
Character to use as decimal separator (default |
'.'
|
big_mark
|
str
|
Thousands separator (default |
','
|
Returns:
| Type | Description |
|---|---|
SummarisedResult
|
A new :class: |
format_estimate_name
¶
format_estimate_name(
result: SummarisedResult,
*,
estimate_name: dict[str, str] | None = None,
keep_not_formatted: bool = True,
use_format_order: bool = True,
) -> SummarisedResult
Combine/rename estimate values using template patterns.
Each key in estimate_name is a display label; each value is a pattern
containing <estimate_name> placeholders, e.g.::
{"N (%)": "<count> (<percentage>%)"}
Rows whose estimate_name appears in a pattern are merged; the
resulting row gets the display label as its estimate_name and the
interpolated string as estimate_value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult
|
A :class: |
required |
estimate_name
|
dict[str, str] | None
|
Mapping of |
None
|
keep_not_formatted
|
bool
|
Whether to keep rows whose |
True
|
use_format_order
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
SummarisedResult
|
A new :class: |
format_header
¶
format_header(
result: DataFrame | SummarisedResult,
header: list[str],
*,
delim: str = HEADER_DELIM,
include_header_name: bool = True,
include_header_key: bool = True,
) -> pl.DataFrame
Pivot columns into multi-level column headers.
Takes a DataFrame (or SummarisedResult's data) and pivots specified columns so their unique values become part of the column names, enabling multi-level headers in formatted tables.
The column names in the output encode header metadata using delim as
a separator. For example, pivoting cohort_name with values
["cohort_1", "cohort_2"] produces columns like::
"[header]cohort_name\n[header_level]cohort_1"
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
DataFrame | SummarisedResult
|
The data to pivot. If a :class: |
required |
header
|
list[str]
|
Column names to pivot into headers. May also contain label strings (not actual column names) that will be inserted as header group labels. |
required |
delim
|
str
|
Delimiter between header levels (default newline). |
HEADER_DELIM
|
include_header_name
|
bool
|
Include the column name in the header. |
True
|
include_header_key
|
bool
|
Include |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
A pivoted :class: |
format_min_cell_count
¶
Replace suppressed count values with <N display strings.
Reads min_cell_count from the result's settings. Rows where
estimate_value is "-" (the suppression sentinel) are replaced
with "<N" where N is the minimum cell count.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult
|
A :class: |
required |
Returns:
| Type | Description |
|---|---|
SummarisedResult
|
A new :class: |
Tidy Helpers¶
tidy_result
¶
Convert a :class:SummarisedResult to a tidy DataFrame.
Equivalent to R's tidy(<summarised_result>):
1. Add settings columns
2. Split all name-level pair columns
3. Keep estimate columns for downstream pivoting
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult
|
The summarised result to tidy. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
A wide :class: |
DataFrame
|
group, strata, and additional variables. |
tidy_columns
¶
Return the column names available after tidying.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult
|
The summarised result. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
List of column names that :func: |
High-Level Tables¶
vis_omop_table
¶
vis_omop_table(
result: SummarisedResult,
*,
estimate_name: dict[str, str] | None = None,
header: list[str] | None = None,
settings_columns: list[str] | None = None,
group_column: list[str] | None = None,
rename: dict[str, str] | None = None,
type: TableType | None = None,
hide: list[str] | None = None,
column_order: list[str] | None = None,
style: TableStyle | None = None,
show_min_cell_count: bool = True,
decimals: dict[str, int] | None = None,
decimal_mark: str = ".",
big_mark: str = ",",
title: str | None = None,
subtitle: str | None = None,
) -> Any
Create a formatted table from a :class:SummarisedResult.
This is the main high-level entry point, equivalent to R's
visOmopTable(). It executes the full format pipeline:
- Format estimate values (numeric precision)
- Show min cell count markers if suppressed
- Format estimate names (combine estimates)
- Split name-level pairs and add settings
- Apply header pivoting
- Render to table
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult
|
A :class: |
required |
estimate_name
|
dict[str, str] | None
|
Mapping of |
None
|
header
|
list[str] | None
|
Columns to pivot into multi-level column headers. |
None
|
settings_columns
|
list[str] | None
|
Settings columns to include in output. |
None
|
group_column
|
list[str] | None
|
Columns to use for row grouping. |
None
|
rename
|
dict[str, str] | None
|
Column rename mapping ( |
None
|
type
|
TableType | None
|
Output type: |
None
|
hide
|
list[str] | None
|
Columns to exclude from output. |
None
|
column_order
|
list[str] | None
|
Explicit column ordering. |
None
|
style
|
TableStyle | None
|
Table style configuration. |
None
|
show_min_cell_count
|
bool
|
Show |
True
|
decimals
|
dict[str, int] | None
|
Override decimal places per estimate type. |
None
|
decimal_mark
|
str
|
Decimal separator character. |
'.'
|
big_mark
|
str
|
Thousands separator character. |
','
|
title
|
str | None
|
Table title. |
None
|
subtitle
|
str | None
|
Table subtitle. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
Any
|
class: |
vis_table
¶
vis_table(
result: DataFrame,
*,
estimate_name: dict[str, str] | None = None,
header: list[str] | None = None,
group_column: list[str] | None = None,
rename: dict[str, str] | None = None,
type: TableType | None = None,
hide: list[str] | None = None,
style: TableStyle | None = None,
title: str | None = None,
subtitle: str | None = None,
) -> Any
Create a formatted table from any DataFrame.
A lower-level function than :func:vis_omop_table — operates on any
:class:~polars.DataFrame, not just :class:SummarisedResult.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
DataFrame
|
Any Polars DataFrame. |
required |
estimate_name
|
dict[str, str] | None
|
Not applicable for plain DataFrames (ignored). |
None
|
header
|
list[str] | None
|
Columns to pivot into headers. |
None
|
group_column
|
list[str] | None
|
Columns to use for row grouping. |
None
|
rename
|
dict[str, str] | None
|
Column rename mapping ( |
None
|
type
|
TableType | None
|
Output type. |
None
|
hide
|
list[str] | None
|
Columns to exclude. |
None
|
style
|
TableStyle | None
|
Table style configuration. |
None
|
title
|
str | None
|
Table title. |
None
|
subtitle
|
str | None
|
Table subtitle. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
format_table
¶
format_table(
x: DataFrame,
*,
type: TableType | None = None,
style: TableStyle | None = None,
na: str | None = None,
title: str | None = None,
subtitle: str | None = None,
group_column: list[str] | None = None,
group_as_column: bool = False,
merge: str = "all_columns",
) -> Any
Render a prepared DataFrame to a table object.
This is the low-level rendering function. Typically called via
:func:vis_omop_table or :func:vis_table, but can be used
directly for maximum control.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
DataFrame
|
A :class: |
required |
type
|
TableType | None
|
Output type ( |
None
|
style
|
TableStyle | None
|
Table style configuration. |
None
|
na
|
str | None
|
String to display for missing values. |
None
|
title
|
str | None
|
Table title. |
None
|
subtitle
|
str | None
|
Table subtitle. |
None
|
group_column
|
list[str] | None
|
Columns for row grouping. |
None
|
group_as_column
|
bool
|
If |
False
|
merge
|
str
|
Column merge strategy ( |
'all_columns'
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
Plots¶
scatter_plot
¶
scatter_plot(
result: SummarisedResult | DataFrame,
*,
x: str,
y: str,
line: bool = False,
point: bool = True,
ribbon: bool = False,
y_min: str | None = None,
y_max: str | None = None,
facet: str | list[str] | None = None,
colour: str | None = None,
style: PlotStyle | None = None,
group: str | None = None,
title: str | None = None,
x_title: str | None = None,
y_title: str | None = None,
) -> Any
Create a scatter/line/ribbon plot from results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult | DataFrame
|
A :class: |
required |
x
|
str
|
Column name for x-axis. |
required |
y
|
str
|
Column name or estimate name for y-axis. |
required |
line
|
bool
|
Whether to connect points with lines. |
False
|
point
|
bool
|
Whether to show points. |
True
|
ribbon
|
bool
|
Whether to show a ribbon (requires y_min and y_max). |
False
|
y_min
|
str | None
|
Column/estimate for ribbon lower bound. |
None
|
y_max
|
str | None
|
Column/estimate for ribbon upper bound. |
None
|
facet
|
str | list[str] | None
|
Column(s) for faceting. A single string creates a single-row facet; a list of two creates a grid (row, col). |
None
|
colour
|
str | None
|
Column for colour aesthetic. |
None
|
style
|
PlotStyle | None
|
Plot style configuration. |
None
|
group
|
str | None
|
Column for grouping (defaults to colour). |
None
|
title
|
str | None
|
Plot title. |
None
|
x_title
|
str | None
|
X-axis title. If |
None
|
y_title
|
str | None
|
Y-axis title. If |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
bar_plot
¶
bar_plot(
result: SummarisedResult | DataFrame,
*,
x: str,
y: str,
position: Literal["dodge", "stack"] = "dodge",
facet: str | list[str] | None = None,
colour: str | None = None,
style: PlotStyle | None = None,
title: str | None = None,
x_title: str | None = None,
y_title: str | None = None,
) -> Any
Create a bar chart from results.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult | DataFrame
|
A :class: |
required |
x
|
str
|
Column name for x-axis (categories). |
required |
y
|
str
|
Column name or estimate for y-axis (bar height). |
required |
position
|
Literal['dodge', 'stack']
|
Bar positioning: |
'dodge'
|
facet
|
str | list[str] | None
|
Column(s) for faceting. |
None
|
colour
|
str | None
|
Column for colour grouping. |
None
|
style
|
PlotStyle | None
|
Plot style configuration. |
None
|
title
|
str | None
|
Plot title. |
None
|
x_title
|
str | None
|
X-axis title. |
None
|
y_title
|
str | None
|
Y-axis title. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
box_plot
¶
box_plot(
result: SummarisedResult | DataFrame,
*,
x: str,
lower: str = "q25",
middle: str = "median",
upper: str = "q75",
y_min: str = "min",
y_max: str = "max",
facet: str | list[str] | None = None,
colour: str | None = None,
style: PlotStyle | None = None,
title: str | None = None,
x_title: str | None = None,
y_title: str | None = None,
) -> Any
Create a box plot from pre-computed summary statistics.
Unlike traditional box plots, this renders from pre-computed quantiles (as found in summarised results), not raw data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
SummarisedResult | DataFrame
|
A :class: |
required |
x
|
str
|
Column for x-axis categories. |
required |
lower
|
str
|
Column/estimate name for Q1 (25th percentile). |
'q25'
|
middle
|
str
|
Column/estimate name for median. |
'median'
|
upper
|
str
|
Column/estimate name for Q3 (75th percentile). |
'q75'
|
y_min
|
str
|
Column/estimate name for whisker minimum. |
'min'
|
y_max
|
str
|
Column/estimate name for whisker maximum. |
'max'
|
facet
|
str | list[str] | None
|
Column(s) for faceting. |
None
|
colour
|
str | None
|
Column for colour grouping. |
None
|
style
|
PlotStyle | None
|
Plot style configuration. |
None
|
title
|
str | None
|
Plot title. |
None
|
x_title
|
str | None
|
X-axis title. |
None
|
y_title
|
str | None
|
Y-axis title. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A |
Style Configuration¶
TableStyle
dataclass
¶
TableStyle(
title_align: str = "left",
title_color: str = "#333333",
header_background: str = "#4361ee",
header_color: str = "#ffffff",
header_align: str = "center",
body_align: str = "right",
group_background: str = "#e8eaf6",
group_color: str = "#333333",
stripe: bool = True,
stripe_color: str = "#f5f5f5",
na_display: str = "–",
font_family: str = "system-ui, -apple-system, sans-serif",
font_size: int = 14,
)
Configuration for table appearance.
Attributes:
| Name | Type | Description |
|---|---|---|
title_align |
str
|
Alignment for the table title
( |
title_color |
str
|
Colour for the title text (CSS colour string). |
header_background |
str
|
Background colour for column headers. |
header_color |
str
|
Text colour for column headers. |
header_align |
str
|
Alignment for column headers. |
body_align |
str
|
Default alignment for body cells. |
group_background |
str
|
Background colour for group label rows. |
group_color |
str
|
Text colour for group label rows. |
stripe |
bool
|
Whether to apply row striping. |
stripe_color |
str
|
Background colour for striped rows. |
na_display |
str
|
String to display for |
font_family |
str
|
Font family for the table. |
font_size |
int
|
Base font size in pixels. |
PlotStyle
dataclass
¶
PlotStyle(
color_palette: list[str] = (
lambda: [
"#4361ee",
"#3a86ff",
"#8338ec",
"#ff006e",
"#fb5607",
"#ffbe0b",
"#06d6a0",
"#118ab2",
"#073b4c",
"#ef476f",
]
)(),
background_color: str = "#ffffff",
text_color: str = "#333333",
grid_color: str = "#e0e0e0",
font_family: str = "system-ui, -apple-system, sans-serif",
font_size: int = 12,
title_size: int = 16,
show_legend: bool = True,
)
Configuration for plot appearance.
Attributes:
| Name | Type | Description |
|---|---|---|
color_palette |
list[str]
|
List of hex colour strings for data series. |
background_color |
str
|
Plot background colour. |
text_color |
str
|
Default text colour. |
grid_color |
str
|
Gridline colour. |
font_family |
str
|
Font family. |
font_size |
int
|
Base font size in points. |
title_size |
int
|
Title font size in points. |
show_legend |
bool
|
Whether to show the legend by default. |
customise_text
¶
customise_text(
x: str | list[str],
*,
fun: Callable[[str], str] | None = None,
custom: dict[str, str] | None = None,
keep: list[str] | None = None,
) -> str | list[str]
Style text strings for display.
Default transformation: replace underscores with spaces and apply sentence case.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
str | list[str]
|
String or list of strings to style. |
required |
fun
|
Callable[[str], str] | None
|
Custom transformation function. If |
None
|
custom
|
dict[str, str] | None
|
Dict of exact replacements ( |
None
|
keep
|
list[str] | None
|
Values to keep unchanged. |
None
|
Returns:
| Type | Description |
|---|---|
str | list[str]
|
Styled string(s), same type as input. |
Examples:
Mock Data¶
mock_summarised_result
¶
Generate a mock :class:SummarisedResult for testing.
Produces results with:
- n_cohorts cohort groups (cohort_1, cohort_2, ...)
- n_strata strata combinations drawn from overall,
age_group &&& sex pairs, and single sex strata.
- Variables: number subjects (count), age (mean, sd),
Medications Amoxiciline (count, percentage).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_cohorts
|
int
|
Number of cohort groups. |
2
|
n_strata
|
int
|
Number of strata combinations (max 9). |
3
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
SummarisedResult
|
class: |