{"spec_id":"histogram-basic","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nhistogram-basic: Basic Histogram\nLibrary: pygal 3.1.3 | Python 3.14.9\nQuality: 83/100 | Updated: 2026-10-28\n\"\"\"\n\nimport sys\n\n\n# This file is named pygal.py which shadows the installed pygal package.\n# Move the script directory to the end so site-packages takes precedence.\n_script_dir = sys.path.pop(0) if sys.path else None\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nimport pygal\nfrom pygal.style import Style\n\n\nif _script_dir is not None:\n    sys.path.append(_script_dir)\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint palette: all eight positions in canonical order\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"]\n\n# Constants\nN_BINS = 20  # enough bins to show the skew and the tails of 500 observations\n\n# Columns: set these to your table's column names\nSCORE = \"Exam score (points)\"  # role: values\nCOUNT = \"Number of students\"  # axis title for the frequency, derived from the values\n\n# Data: replace this block with your own table, for example df = pd.read_csv(\"scores.csv\")\nrng = np.random.default_rng(42)\ndf = pd.DataFrame({SCORE: rng.beta(a=5, b=2, size=500) * 60 + 35})\n\n# Plot: reads only df and the constants above\ncounts, bin_edges = np.histogram(df[SCORE].dropna(), bins=N_BINS)\nhist_data = [\n    (int(count), float(lo), float(hi)) for count, lo, hi in zip(counts, bin_edges[:-1], bin_edges[1:], strict=True)\n]\n\n# Style: thin bin edges in the page color keep neighboring bars distinguishable without gaps\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT_PALETTE,\n    font_family=\"DejaVu Sans, Helvetica, Arial, sans-serif\",\n    title_font_family=\"DejaVu Sans, Helvetica, Arial, sans-serif\",\n    title_font_size=66,\n    label_font_size=56,\n    major_label_font_size=44,\n    legend_font_size=44,\n    value_font_size=36,\n    stroke_width=2.5,\n)\ncustom_style.opacity = \"1\"\ncustom_style.opacity_hover = \"0.85\"\n\nchart = pygal.Histogram(\n    css=[\"file://style.css\", \"file://graph.css\", f\"inline:.rect {{ stroke: {PAGE_BG}; stroke-width: 3; }}\"],\n    width=3200,\n    height=1800,\n    style=custom_style,\n    title=\"histogram-basic · python · pygal · anyplot.ai\",\n    x_title=SCORE,\n    y_title=COUNT,\n    show_legend=False,\n    show_y_guides=True,\n    show_x_guides=False,\n    tooltip_fancy_mode=True,\n    print_values=False,\n    margin_bottom=100,\n    margin_left=80,\n    margin_right=60,\n    margin_top=80,\n)\nchart.add(COUNT, hist_data)\n\n# Save\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}