Skip to content

Commit

Permalink
Add option to label each segment's value
Browse files Browse the repository at this point in the history
  • Loading branch information
nmalkin committed Feb 4, 2022
1 parent c24ff47 commit 6d334d9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
2 changes: 2 additions & 0 deletions plot_likert/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"darkblue",
]

default_label_color = "white"

# default color scheme with neutral removed
likert4: Colors = list(default)
likert4.pop(len(likert4) // 2)
Expand Down
42 changes: 42 additions & 0 deletions plot_likert/plot_likert.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
HIDE_EXCESSIVE_TICK_LABELS = True
PADDING_LEFT = 0.02 # fraction of the total width to use as padding
PADDING_RIGHT = 0.04 # fraction of the total width to use as padding
BAR_LABEL_FORMAT = (
"%d" # if showing labels, how should the number be formatted? e.g., "%.2g"
)
BAR_LABEL_SIZE_CUTOFF = 0.05


class PlotLikertError(ValueError):
Expand All @@ -50,6 +54,8 @@ def plot_counts(
figsize=None,
xtick_interval: typing.Optional[int] = None,
compute_percentages: bool = False,
bar_labels: bool = False,
bar_labels_color: str = "white",
**kwargs,
) -> matplotlib.axes.Axes:
"""
Expand All @@ -75,6 +81,10 @@ def plot_counts(
Controls the interval between x-axis ticks.
compute_percentages : bool, default = True,
Convert the given response counts to percentages and display the counts as percentages in the plot.
bar_labels : bool, default = False
Show a label with the value of each bar segment on top of it
bar_labels_color: str, default = "white"
If showing bar labels, use this color for the text
**kwargs
Options to pass to pandas plotting method.
Expand Down Expand Up @@ -181,6 +191,30 @@ def plot_counts(
x_min, x_max = axes.get_xlim()
axes.set_xlim(x_min - padding_left, x_max - padding_right)

# Add labels
if bar_labels:
bar_label_format = BAR_LABEL_FORMAT + ("%%" if compute_percentages else "")
bar_size_cutoff = counts_sum * BAR_LABEL_SIZE_CUTOFF

for segment in axes.containers[1:]: # the first container is the padding
labels = axes.bar_label(
segment,
label_type="center",
fmt=bar_label_format,
padding=0,
color=bar_labels_color,
weight="bold",
)

# Remove labels that don't fit because the bars are too small
for label in labels:
label_text = label.get_text()
if compute_percentages:
label_text = label_text.rstrip("%")
number = float(label_text)
if number < bar_size_cutoff:
label.set_text("")

return axes


Expand Down Expand Up @@ -290,6 +324,8 @@ def plot_likert(
drop_zeros: bool = False,
figsize=None,
xtick_interval: typing.Optional[int] = None,
bar_labels: bool = False,
bar_labels_color: str = "white",
**kwargs,
) -> matplotlib.axes.Axes:
"""
Expand Down Expand Up @@ -319,6 +355,10 @@ def plot_likert(
similarly to matplotlib
xtick_interval : int
Controls the interval between x-axis ticks.
bar_labels : bool, default = False
Show a label with the value of each bar segment on top of it
bar_labels_color: str, default = "white"
If showing bar labels, use this color for the text
**kwargs
Options to pass to pandas plotting method.
Expand All @@ -345,6 +385,8 @@ def plot_likert(
figsize=figsize,
xtick_interval=xtick_interval,
compute_percentages=plot_percentage,
bar_labels=bar_labels,
bar_labels_color=bar_labels_color,
**kwargs,
)

Expand Down

0 comments on commit 6d334d9

Please sign in to comment.