Basic Word Cloud — Seaborn

A word cloud displays text data where word size represents frequency or importance. Words are arranged to fill available space, creating a visual summary of text content that highlights prominent terms and patterns. This visualization is ideal for quickly identifying the most common themes or keywords in a body of text.

Basic Word Cloud rendered with Seaborn

Renders

Python source (Seaborn)

""" anyplot.ai
wordcloud-basic: Basic Word Cloud
Library: seaborn 0.13.2 | Python 3.13.14
Quality: 86/100 | Updated: 2026-08-04
"""

import os

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns


# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"

# Imprint palette — canonical order, first series always #009E73 — built via
# sns.color_palette() so seaborn validates/normalizes the hex values instead of
# using the raw list directly.
IMPRINT_PALETTE = sns.color_palette(
    ["#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD", "#954477", "#99B314"]
).as_hex()

sns.set_theme(
    style="white",
    rc={"figure.facecolor": PAGE_BG, "axes.facecolor": PAGE_BG, "font.family": "sans-serif", "text.color": INK},
)
# Drives the title's font size below (plt.rcParams["axes.titlesize"]) so the
# text scale is governed by seaborn's context system, not a bare literal.
sns.set_context("notebook", font_scale=1.0)

# Data - tech-skill mentions from a developer survey (frequency = respondent count).
# Brand/product names and acronyms keep their established casing (Python, AWS, SQL,
# ...); generic descriptive terms are lowercased per the spec's preprocessing note.
word_frequencies = {
    "Python": 180,
    "JavaScript": 160,
    "React": 145,
    "Docker": 135,
    "AWS": 130,
    "SQL": 125,
    "Linux": 120,
    "Git": 115,
    "API": 110,
    "DevOps": 105,
    "cloud": 100,
    "testing": 95,
    "agile": 90,
    "TypeScript": 87,
    "Node": 84,
    "Kubernetes": 81,
    "MongoDB": 78,
    "security": 75,
    "Azure": 72,
    "REST": 69,
    "Redis": 66,
    "GraphQL": 63,
    "analytics": 60,
    "PostgreSQL": 57,
    "Terraform": 54,
    "backend": 51,
    "frontend": 48,
    "CICD": 45,
    "Spark": 42,
    "Kafka": 39,
    "Flask": 36,
    "Django": 33,
    "Pandas": 30,
    "NumPy": 28,
    "FastAPI": 26,
    "Vue": 24,
    "Angular": 22,
    "Nginx": 20,
    "OAuth": 18,
    "Jenkins": 16,
    "Ansible": 14,
    "Prometheus": 12,
    "Grafana": 10,
    "RabbitMQ": 8,
    "Elasticsearch": 7,
    "Hadoop": 6,
    "Airflow": 5,
    "dbt": 4,
    "Pulumi": 3,
    "Istio": 2,
}

# Sort largest-frequency-first so big words claim the center before small ones fill the gaps
words = sorted(word_frequencies, key=word_frequencies.get, reverse=True)
frequencies = np.array([word_frequencies[w] for w in words], dtype=float)

min_freq, max_freq = frequencies.min(), frequencies.max()
font_sizes = 8 + (frequencies - min_freq) / (max_freq - min_freq) * 22

# Plot — collision-aware spiral placement (checks each word's real rendered
# bounding box against every word already placed, instead of a fixed spiral
# offset that lets neighbors overlap)
fig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)
ax.set_facecolor(PAGE_BG)

x_half, y_half = 1.0, 0.5625
ax.set_xlim(-x_half, x_half)
ax.set_ylim(-y_half, y_half)
ax.axis("off")

fig.canvas.draw()
renderer = fig.canvas.get_renderer()
inv = ax.transData.inverted()


def half_extent_data(word, fontsize):
    probe = ax.text(0, 0, word, fontsize=fontsize, fontweight="bold", ha="center", va="center", alpha=0)
    bbox = probe.get_window_extent(renderer=renderer)
    probe.remove()
    (x0, y0), (x1, y1) = inv.transform([(bbox.x0, bbox.y0), (bbox.x1, bbox.y1)])
    return (x1 - x0) / 2, (y1 - y0) / 2


def collides(x, y, hw, hh, pad, boxes):
    x0, y0, x1, y1 = x - hw - pad, y - hh - pad, x + hw + pad, y + hh + pad
    for bx0, by0, bx1, by1 in boxes:
        if x0 < bx1 and x1 > bx0 and y0 < by1 and y1 > by0:
            return True
    return False


golden_angle = np.pi * (3 - np.sqrt(5))
max_steps = 900
# Normalized radius up to sqrt(2) so the spiral (scaled independently per axis
# below) reaches the canvas corners instead of tracing an inscribed ellipse.
spiral_scale = np.sqrt(2) / np.sqrt(max_steps)
placed_boxes = []
pad = 0.005

for idx, (word, target_fontsize) in enumerate(zip(words, font_sizes, strict=True)):
    color = IMPRINT_PALETTE[idx % len(IMPRINT_PALETTE)]
    fontsize = target_fontsize
    # A word that can't find a free spot at its target size shrinks and
    # retries, instead of falling back to a fixed spot where it would
    # stack on top of whatever was already placed there.
    for _shrink_attempt in range(6):
        hw, hh = half_extent_data(word, fontsize)
        x, y, found = 0.0, 0.0, False
        for step in range(max_steps):
            angle = step * golden_angle
            norm_radius = spiral_scale * np.sqrt(step)
            cand_x = np.clip(norm_radius * np.cos(angle) * x_half, -x_half + hw, x_half - hw)
            cand_y = np.clip(norm_radius * np.sin(angle) * y_half, -y_half + hh, y_half - hh)
            if not collides(cand_x, cand_y, hw, hh, pad, placed_boxes):
                x, y, found = cand_x, cand_y, True
                break
        if found:
            break
        fontsize *= 0.82
    placed_boxes.append((x - hw, y - hh, x + hw, y + hh))
    ax.text(x, y, word, fontsize=fontsize, fontweight="bold", ha="center", va="center", color=color)

ax.set_title(
    "wordcloud-basic · python · seaborn · anyplot.ai",
    fontsize=plt.rcParams["axes.titlesize"],
    fontweight="medium",
    color=INK,
    pad=14,
)

plt.savefig(f"plot-{THEME}.png", dpi=400, facecolor=PAGE_BG)

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/wordcloud-basic/seaborn/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "wordcloud-basic",
  "language": "python",
  "library": "seaborn",
  "page": "https://anyplot.ai/wordcloud-basic/python/seaborn",
  "hub": "https://anyplot.ai/wordcloud-basic",
  "code_json": "https://api.anyplot.ai/specs/wordcloud-basic/seaborn/code",
  "spec_json": "https://api.anyplot.ai/specs/wordcloud-basic",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/wordcloud-basic/python/seaborn/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/wordcloud-basic/python/seaborn/plot-dark.png",
  "quality_score": 86.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Basic Word Cloud on anyplot.ai.

Other implementations