Introduction
A dashboard gauge looks impressive but wastes space and is hard to compare across many rows at once — a surgeon's success rate, a region's vaccination rate, a department's budget spend, each needing its own dial. PlotBulletChart replaces the gauge with a compact horizontal bullet chart: a dot for the actual measure, a vertical line for the target, and shaded background bands for qualitative performance ranges (poor, satisfactory, good), all stacked in a single readable list.
Teaching Note
Bullet charts are essential for:
- Healthcare: Monitoring surgeon success rates against departmental benchmarks and thresholds.
- Epidemiology: Tracking actual vaccination rates vs. herd immunity targets across regions.
- Project Management: Monitoring task completion percentages vs. project milestones.
- Public Health: Comparing current emergency room wait times against historical performance bands.
- Data Science: Evaluating model accuracy metrics against baseline and state-of-the-art targets.
- Operations: Monitoring production efficiency across several manufacturing lines.
- Finance: Visualizing actual expenditure vs. budget targets across multiple departments.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
dataframerequired | pd.DataFrame | — | The pandas DataFrame containing the performance data to be plotted. |
value_column_namerequired | str | — | The name of the column containing the primary measure (performance value). |
grouping_column_namerequired | str | — | The name of the column representing the categories or groups for each bullet. |
target_value_column_name | str | None | The name of the column containing the target values for each group. Defaults to None. |
list_of_limit_columns | list of str | None | A list of column names containing the qualitative range boundaries (e.g., ['poor', 'fair', 'good']). Defaults to None. |
value_maximum | float | None | The absolute maximum value for the chart's x-axis. If None, it is inferred from the data. Defaults to None. |
value_minimum | float | 0 | The absolute minimum value for the chart's x-axis. Defaults to 0. |
display_order_list | list of str | None | A specific list of category names to define the vertical order of the bullets. If None, categories are sorted by their value column. Defaults to None. |
null_background_color | str | '#dbdbdb' | The hex color code for the background area where no qualitative ranges are defined. Defaults to '#dbdbdb'. |
background_color_palette | str | None | The name of the seaborn color palette used for qualitative ranges. If None, a professional greyscale palette is used. Defaults to None. |
background_alpha | float | 0.8 | The transparency level (alpha) of the qualitative range background colors. Defaults to 0.8. |
value_dot_size | int | 200 | The area of the marker representing the primary measure. Defaults to 200. |
value_dot_color | str | '#383838' | The hex color code for the value marker. Defaults to '#383838'. |
value_dot_color_by_level | bool | False | Whether to color the value marker based on which qualitative range it falls into. Defaults to False. |
value_dot_outline_color | str | '#ffffff' | The hex color code for the border of the value marker. Defaults to '#ffffff'. |
value_dot_outline_width | int | 2 | The width of the border around the value marker. Defaults to 2. |
target_line_color | str | '#bf3228' | The hex color code for the target value marker line. Defaults to '#bf3228'. |
target_line_width | int | 4 | The width of the vertical target line. Defaults to 4. |
figure_size | tuple of int | (8, 6) | Dimensions of the output figure as a (width, height) tuple in inches. Defaults to (8, 6). |
show_value_labels | bool | True | Whether to display numeric text labels next to each value marker. Defaults to True. |
value_label_color | str | '#262626' | The hex color code for the numeric text labels. Defaults to '#262626'. |
value_label_format | str | '{:.0f}' | The Python string format for the numeric labels (e.g., '{:.1f}%'). Defaults to '{:.0f}'. |
value_label_font_size | int | 12 | The font size for the numeric text labels. Defaults to 12. |
value_label_spacing | float | 0.65 | Vertical offset for positioning the numeric label relative to the marker. Defaults to 0.65. |
value_label_padding | float | 0.3 | Padding inside the background box of the numeric label. Defaults to 0.3. |
value_label_background_color | str | '#ffffff' | The hex color code for the background box behind the numeric label. Defaults to '#ffffff'. |
value_label_background_alpha | float | 0.85 | The transparency of the numeric label's background box. Defaults to 0.85. |
title_for_plot | str | None | The primary title text displayed at the top of the chart. Defaults to None. |
subtitle_for_plot | str | None | Descriptive subtitle text displayed below the main title. Defaults to None. |
caption_for_plot | str | None | Explanatory text or notes displayed at the bottom of the plot. Defaults to None. |
data_source_for_plot | str | None | Text identifying the source of the data, appended to the caption. Defaults to None. |
title_y_indent | float | 1.15 | Vertical offset for the title position relative to the axes. Defaults to 1.15. |
subtitle_y_indent | float | 1.1 | Vertical offset for the subtitle position relative to the axes. Defaults to 1.1. |
caption_y_indent | float | -0.15 | Vertical offset for the caption position relative to the axes. Defaults to -0.15. |
filepath_to_save_plot | str | None | The local path (ending in .png or .jpg) where the plot should be exported. If None, the file is not saved. Defaults to None. |
Returns
None — the function displays the plot using matplotlib and optionally saves it to disk.
Example
python
from analysistoolbox.visualizations import PlotBulletChart
import pandas as pd
# Healthcare: surgeon success rates vs. target and benchmarks
surgeon_df = pd.DataFrame({
'Surgeon': ['Dr. Smith', 'Dr. Jones', 'Dr. Brown'],
'Success Rate': [92, 88, 95],
'Target': [90, 90, 90],
'Poor': [70, 70, 70],
'Good': [85, 85, 85],
'Excellent': [95, 95, 95]
})
PlotBulletChart(
surgeon_df, 'Success Rate', 'Surgeon', 'Target',
list_of_limit_columns=['Poor', 'Good', 'Excellent'],
title_for_plot="Cardiac Surgery Success Rates",
subtitle_for_plot="Individual surgeon performance against hospital standards"
)