ANALYSIS TOOL BOX

Visualizations

PlotDotPlot

Generate a formatted horizontal dot plot (dumbbell chart) to compare two groups.

visualizationchartsplottinggraphs

Introduction

"Did this get better or worse, and by how much, for each category" — pre/post, treatment/control, this year vs. last — is a change question, and a dumbbell chart answers it more directly than two separate bar charts ever could. PlotDotPlot draws one dot per group per category, connects them with a line whose length and direction show the magnitude and sign of the change, and can sort categories by that delta so the biggest movers are the easiest to spot.

Teaching Note

Dot plots (Dumbbell charts) are essential for:

  • Epidemiology: Comparing disease prevalence rates before and after a public health intervention.
  • Healthcare: Visualizing patient symptom scores before and after a specific clinical treatment.
  • Data Science: Comparing model accuracy metrics across two different algorithm configurations.
  • Public Health: Monitoring the shift in regional particulate matter levels over a 10-year period.
  • Marketing: Analyzing the lift in customer engagement for treatment vs. control groups in an A/B test.
  • Economics: Visualizing the change in unemployment rates across multiple districts during a recession.
  • Quality Control: Comparing defect rates between two different manufacturing facilities or shifts.

Parameters

ParameterTypeDefaultDescription
dataframerequiredpd.DataFrameThe pandas DataFrame containing the categorical, numeric, and group columns.
categorical_column_namerequiredstrThe name of the column representing the categories (y-axis).
value_column_namerequiredstrThe name of the column representing the numeric values (x-axis).
group_column_namerequiredstrThe name of the categorical column with exactly two unique values (e.g., 'Year', 'Group').
group_1_colorstr'#4257f5'The hex color code for the first group's dots. Defaults to '#4257f5'.
group_2_colorstr'#ccd2ff'The hex color code for the second group's dots. Defaults to '#ccd2ff'.
dot_sizeint20The size of the marker dots. Defaults to 20.
dot_alphafloat1The transparency level (alpha) of the marker dots (0 to 1). Defaults to 1.
zero_line_groupstrNoneThe name of a group to treat as the baseline (zero-point). If provided, values are expressed as deltas from this group. Defaults to None.
connect_dotsboolTrueWhether to draw a connecting line between the two dots in each category. Defaults to True.
connect_line_colorstr'#666666'The hex color code for the connecting lines. Defaults to '#666666'.
connect_line_alphafloat0.4The transparency of the connecting lines. Defaults to 0.4.
connect_line_widthfloat1.0The thickness of the connecting lines. Defaults to 1.0.
connect_line_stylestr'dashed'Matplotlib line style for the connecting lines (e.g., 'solid', 'dashed'). Defaults to 'dashed'.
dict_of_connect_line_labelsdictNoneA dictionary mapping category names to custom text labels for their connecting lines. Defaults to None.
connect_line_label_fontsizeint11The font size for the connecting line labels. Defaults to 11.
connect_line_label_fontsize_fontweightstr'bold'The font weight for the connecting line labels (e.g., 'bold', 'normal'). Defaults to 'bold'.
connect_line_label_colorstr'#262626'The hex color code for the connecting line labels. Defaults to '#262626'.
show_connect_line_labels_in_marginboolFalseWhether to display connecting line labels in the right margin instead of centered on the line. Defaults to False.
connect_line_label_marginfloat0.5The horizontal offset for labels when show_connect_line_labels_in_margin is True. Defaults to 0.5.
display_order_listlistNoneA specific list of categories for the y-axis. If None, categories are sorted by the absolute difference between groups. Defaults to None.
figure_sizetuple(10, 6)Dimensions of the output figure as a (width, height) tuple in inches. Defaults to (10, 6).
show_x_axisboolFalseWhether to display the x-axis tick marks and labels. Defaults to False.
show_data_labelsboolTrueWhether to display numeric text labels for the value dots. Defaults to True.
decimal_places_for_data_labelint1Number of decimal places for numeric data labels. Defaults to 1.
data_label_fontsizeint11The font size for the numeric text labels. Defaults to 11.
data_label_fontweightstr'bold'The font weight for the numeric text labels. Defaults to 'bold'.
data_label_colorstr'#262626'The hex color code for the numeric text labels. Defaults to '#262626'.
title_for_plotstrNoneThe primary title text at the top of the chart. Defaults to None.
subtitle_for_plotstrNoneDescriptive subtitle text below the main title. Defaults to None.
caption_for_plotstrNoneExplanatory text or notes at the bottom of the plot. Defaults to None.
data_source_for_plotstrNoneText identifying the data source, appended to the caption. Defaults to None.
title_y_indentfloat1.15Vertical offset for the title position. Defaults to 1.15.
subtitle_y_indentfloat1.1Vertical offset for the subtitle position. Defaults to 1.1.
caption_y_indentfloat-0.15Vertical offset for the caption position. Defaults to -0.15.
filepath_to_save_plotstrNoneThe 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 dot plot using matplotlib and optionally saves it to disk.

Example

python
from analysistoolbox.visualizations import PlotDotPlot
import pandas as pd

# Epidemiology: infection rates before and after vaccination program
epi_df = pd.DataFrame({
    'Province': ['North', 'South', 'East', 'West'] * 2,
    'Year': ['2023', '2023', '2023', '2023', '2024', '2024', '2024', '2024'],
    'Incidence': [120, 150, 95, 210, 45, 80, 55, 130]
})
PlotDotPlot(
    epi_df, 'Province', 'Incidence', 'Year',
    title_for_plot="Influenza Incidence Reduction",
    subtitle_for_plot="Pre (2023) vs. Post (2024) vaccination campaign data",
    group_1_color="#e74c3c", group_2_color="#27ae60"
)