GitHub-style commit activity heatmap
Engineering — week × day of week
Example from the compendium of canonical charts
Python Code
"""Engineering — GitHub-style commit activity heatmap (week × day of week)."""
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import requests, warnings
REPO = "plotly/plotly.js"
COMMITS_URL = f"https://api.github.com/repos/{REPO}/stats/commit_activity"
DOW_LABELS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
def fetch_commit_activity():
warnings.filterwarnings("ignore")
requests.packages.urllib3.disable_warnings()
headers = {"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28"}
r = requests.get(COMMITS_URL, headers=headers, verify=False, timeout=30)
if r.status_code != 200:
raise ValueError(f"status {r.status_code}")
data = r.json()
if not isinstance(data, list) or len(data) == 0:
raise ValueError("empty response")
return data
def generate():
print(f"fetching commit activity for {REPO} …")
weeks_data = None
try:
weeks_data = fetch_commit_activity()
print(f" got {len(weeks_data)} weeks")
except Exception as e:
print(f" fetch failed ({e}), using synthetic data")
if weeks_data is not None:
# Each item: {"days": [sun,mon,...,sat], "total": N, "week": unix_ts}
n_weeks = len(weeks_data)
commits = np.zeros((n_weeks, 7), dtype=float)
week_starts = []
for i, w in enumerate(weeks_data):
commits[i] = w.get("days", [0] * 7)
week_starts.append(pd.Timestamp(w["week"], unit="s"))
week_labels = [f"W{i+1}" if i % 4 != 0 else ts.strftime("%b '%y")
for i, ts in enumerate(week_starts)]
else:
rng = np.random.default_rng(134)
n_weeks = 52
# Simulate: more commits mid-week, seasonal variation
base = rng.poisson(2, (n_weeks, 7)).astype(float)
base[:, 0] *= 0.2 # less on Sunday
base[:, 6] *= 0.3 # less on Saturday
base[:, 1:5] *= 1.5 # more Mon-Thu
# Seasonal dip in Aug
base[28:32] *= 0.4
commits = base
week_labels = [f"W{i+1}" for i in range(n_weeks)]
# Layout: x=week, y=day of week (Mon at top)
# Reorder days: Mon to Sun (0=Mon ... 6=Sun)
DOW_ORDER = [1, 2, 3, 4, 5, 6, 0] # Mon...Sat, Sun
DOW_DISPLAY = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
z = commits[:, DOW_ORDER].T # shape (7, n_weeks)
fig = go.Figure()
fig.add_trace(go.Heatmap(
x=list(range(len(week_labels))),
y=DOW_DISPLAY,
z=z,
colorscale=[
[0.0, "#ebedf0"], # empty / GitHub light grey
[0.001,"#9be9a8"],
[0.25, "#40c463"],
[0.6, "#30a14e"],
[1.0, "#216e39"], # GitHub dark green
],
zmin=0,
colorbar=dict(title="Commits", thickness=12, len=0.6),
xgap=2, ygap=2,
hovertemplate="Week %{x}<br>%{y}: %{z:.0f} commits<extra></extra>",
))
# Month separator annotations
tick_vals, tick_texts = [], []
for i, lbl in enumerate(week_labels):
if "'" in lbl: # month label
tick_vals.append(i)
tick_texts.append(lbl)
fig.update_layout(
xaxis=dict(
tickvals=tick_vals,
ticktext=tick_texts,
tickangle=0,
showgrid=False,
),
yaxis=dict(showgrid=False, autorange="reversed"),
margin=dict(t=30, b=50, l=60, r=80),
height=220,
)
return fig
if __name__ == "__main__":
generate()
Made with Plotly