Basic Count Plot — Bokeh

A count plot displays the frequency of observations in each category of a categorical variable using vertical bars. Unlike a basic bar chart that requires pre-computed values, a count plot automatically counts occurrences from raw data. This makes it ideal for quick exploratory analysis of categorical distributions without manual aggregation.

Basic Count Plot rendered with Bokeh

Python source (Bokeh)

""" anyplot.ai
count-basic: Basic Count Plot
Library: bokeh 3.9.0 | Python 3.13.13
Quality: 84/100 | Updated: 2026-05-07
"""

import os
import sys
import time
from pathlib import Path


sys.path = [p for p in sys.path if "implementations" not in p]

import numpy as np
from bokeh.io import output_file, save
from bokeh.models import ColumnDataSource, LabelSet
from bokeh.plotting import figure
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
BRAND = "#009E73"  # Okabe-Ito position 1

# Data - Survey responses simulating a customer satisfaction survey
np.random.seed(42)
responses = np.random.choice(
    ["Very Satisfied", "Satisfied", "Neutral", "Dissatisfied", "Very Dissatisfied"],
    size=200,
    p=[0.25, 0.35, 0.20, 0.12, 0.08],
)

# Count occurrences
categories, counts = np.unique(responses, return_counts=True)
# Sort by count descending for better readability
sorted_indices = np.argsort(-counts)
categories = categories[sorted_indices]
counts = counts[sorted_indices]

# Create data source
source = ColumnDataSource(
    data={"category": categories.tolist(), "count": counts.tolist(), "label": [str(c) for c in counts]}
)

# Create figure with categorical x-axis
p = figure(
    x_range=categories.tolist(),
    width=4800,
    height=2700,
    title="count-basic · bokeh · anyplot.ai",
    x_axis_label="Response Category",
    y_axis_label="Number of Responses",
    toolbar_location=None,
)

# Plot bars with Okabe-Ito green
p.vbar(x="category", top="count", source=source, width=0.7, color=BRAND, alpha=0.85, line_color=INK_SOFT, line_width=2)

# Add count labels above bars
labels = LabelSet(
    x="category",
    y="count",
    text="label",
    source=source,
    text_align="center",
    text_baseline="bottom",
    y_offset=10,
    text_font_size="22pt",
    text_color=INK_SOFT,
)
p.add_layout(labels)

# Style the plot
p.title.text_font_size = "28pt"
p.title.align = "center"
p.title.text_color = INK
p.xaxis.axis_label_text_font_size = "22pt"
p.yaxis.axis_label_text_font_size = "22pt"
p.xaxis.axis_label_text_color = INK
p.yaxis.axis_label_text_color = INK
p.xaxis.major_label_text_font_size = "18pt"
p.yaxis.major_label_text_font_size = "18pt"
p.xaxis.major_label_text_color = INK_SOFT
p.yaxis.major_label_text_color = INK_SOFT

# Grid styling
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = INK
p.ygrid.grid_line_alpha = 0.10
p.xaxis.axis_line_color = INK_SOFT
p.yaxis.axis_line_color = INK_SOFT
p.xaxis.major_tick_line_color = INK_SOFT
p.yaxis.major_tick_line_color = INK_SOFT

# Axis and background
p.xaxis.major_label_orientation = 0.4
p.y_range.start = 0
p.y_range.end = max(counts) * 1.15
p.background_fill_color = PAGE_BG
p.border_fill_color = PAGE_BG
p.outline_line_color = INK_SOFT

# Save files in script directory
script_dir = Path(__file__).parent
html_path = script_dir / f"plot-{THEME}.html"
png_path = script_dir / f"plot-{THEME}.png"

output_file(str(html_path))
save(p)

# Screenshot with headless Chrome
W, H = 4800, 2700
opts = Options()
for arg in (
    "--headless=new",
    "--no-sandbox",
    "--disable-dev-shm-usage",
    "--disable-gpu",
    f"--window-size={W},{H}",
    "--hide-scrollbars",
):
    opts.add_argument(arg)
driver = webdriver.Chrome(options=opts)
driver.set_window_size(W, H)
driver.get(f"file://{html_path.resolve()}")
time.sleep(3)
driver.save_screenshot(str(png_path))
driver.quit()

Part of Basic Count Plot on anyplot.ai.

Other implementations