|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | heatmap-basic: Basic Heatmap |
3 | | -Library: plotnine 0.15.2 | Python 3.13.11 |
4 | | -Quality: 92/100 | Created: 2025-12-23 |
| 3 | +Library: plotnine 0.15.3 | Python 3.14.3 |
| 4 | +Quality: /100 | Updated: 2026-02-15 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import numpy as np |
8 | 8 | import pandas as pd |
9 | 9 | from plotnine import ( |
10 | 10 | aes, |
11 | 11 | element_blank, |
| 12 | + element_rect, |
12 | 13 | element_text, |
13 | 14 | geom_text, |
14 | 15 | geom_tile, |
15 | 16 | ggplot, |
16 | 17 | labs, |
| 18 | + scale_color_identity, |
17 | 19 | scale_fill_gradient2, |
| 20 | + scale_x_discrete, |
| 21 | + scale_y_discrete, |
18 | 22 | theme, |
19 | 23 | theme_minimal, |
20 | 24 | ) |
21 | 25 |
|
22 | 26 |
|
23 | | -# Data - 8x8 matrix with meaningful patterns (performance metrics by region and quarter) |
| 27 | +# Data - 8x8 matrix: quarterly growth rates (%) by department |
24 | 28 | np.random.seed(42) |
25 | | -rows = ["Region A", "Region B", "Region C", "Region D", "Region E", "Region F", "Region G", "Region H"] |
26 | | -cols = ["Q1 2023", "Q2 2023", "Q3 2023", "Q4 2023", "Q1 2024", "Q2 2024", "Q3 2024", "Q4 2024"] |
| 29 | +departments = ["Engineering", "Marketing", "Sales", "Finance", "Operations", "HR", "Research", "Support"] |
| 30 | +quarters = ["Q1 '23", "Q2 '23", "Q3 '23", "Q4 '23", "Q1 '24", "Q2 '24", "Q3 '24", "Q4 '24"] |
27 | 31 |
|
28 | | -# Create data with a trend and variation |
29 | | -base_values = np.linspace(-30, 40, 8) # Trend across columns |
30 | | -row_effects = np.random.uniform(-10, 10, 8) # Row-specific offsets |
| 32 | +# Growth rates with a recovery trend and departmental variation |
| 33 | +base_trend = np.linspace(-15, 20, 8) |
| 34 | +dept_offsets = np.array([-5, 8, 12, -2, 3, -8, 6, -4]) |
31 | 35 | values = np.zeros((8, 8)) |
32 | 36 | for i in range(8): |
33 | 37 | for j in range(8): |
34 | | - values[i, j] = base_values[j] + row_effects[i] + np.random.uniform(-8, 8) |
| 38 | + values[i, j] = round(base_trend[j] + dept_offsets[i] + np.random.normal(0, 4), 1) |
35 | 39 |
|
36 | | -# Create long-form DataFrame for plotnine |
37 | | -data = [] |
38 | | -for i, row in enumerate(rows): |
39 | | - for j, col in enumerate(cols): |
40 | | - data.append({"x": col, "y": row, "value": round(values[i, j], 1)}) |
| 40 | +# Long-form DataFrame |
| 41 | +records = [] |
| 42 | +for i, dept in enumerate(departments): |
| 43 | + for j, qtr in enumerate(quarters): |
| 44 | + records.append({"Department": dept, "Quarter": qtr, "Growth": values[i, j]}) |
41 | 45 |
|
42 | | -df = pd.DataFrame(data) |
| 46 | +df = pd.DataFrame(records) |
| 47 | +df["Quarter"] = pd.Categorical(df["Quarter"], categories=quarters, ordered=True) |
| 48 | +df["Department"] = pd.Categorical(df["Department"], categories=departments[::-1], ordered=True) |
43 | 49 |
|
44 | | -# Preserve ordering |
45 | | -df["x"] = pd.Categorical(df["x"], categories=cols, ordered=True) |
46 | | -df["y"] = pd.Categorical(df["y"], categories=rows[::-1], ordered=True) # Reverse for top-to-bottom |
| 50 | +# Conditional text color: white on dark blue cells, dark on light cells |
| 51 | +df["text_color"] = df["Growth"].apply(lambda v: "white" if v < -10 else "#333333") |
| 52 | + |
| 53 | +# Format labels with sign |
| 54 | +df["label"] = df["Growth"].apply(lambda v: f"{v:+.1f}") |
47 | 55 |
|
48 | 56 | # Plot |
49 | 57 | plot = ( |
50 | | - ggplot(df, aes(x="x", y="y", fill="value")) |
51 | | - + geom_tile(color="white", size=0.5) |
52 | | - + geom_text(aes(label="value"), size=12, color="black") |
53 | | - + scale_fill_gradient2( |
54 | | - low="#306998", # Python Blue for negative |
55 | | - mid="white", |
56 | | - high="#FFD43B", # Python Yellow for positive |
57 | | - midpoint=0, |
58 | | - name="Value", |
59 | | - ) |
60 | | - + labs(x="Time Period", y="Region", title="heatmap-basic · plotnine · pyplots.ai") |
| 58 | + ggplot(df, aes(x="Quarter", y="Department")) |
| 59 | + + geom_tile(aes(fill="Growth"), color="white", size=0.8) |
| 60 | + + geom_text(aes(label="label", color="text_color"), size=11, fontweight="bold", show_legend=False) |
| 61 | + + scale_fill_gradient2(low="#306998", mid="#f5f5f0", high="#FFD43B", midpoint=0, name="Growth (%)") |
| 62 | + + scale_color_identity() |
| 63 | + + scale_x_discrete(expand=(0, 0.5)) |
| 64 | + + scale_y_discrete(expand=(0, 0.5)) |
| 65 | + + labs(x="", y="", title="Quarterly Growth by Department · heatmap-basic · plotnine · pyplots.ai") |
61 | 66 | + theme_minimal() |
62 | 67 | + theme( |
63 | 68 | figure_size=(16, 9), |
64 | | - text=element_text(size=14), |
65 | | - axis_title=element_text(size=20), |
66 | | - axis_text_x=element_text(size=14, rotation=45, ha="right"), |
67 | | - axis_text_y=element_text(size=16), |
68 | | - plot_title=element_text(size=24), |
| 69 | + text=element_text(family="sans-serif"), |
| 70 | + plot_title=element_text(size=22, ha="center", margin={"b": 15}), |
| 71 | + axis_text_x=element_text(size=16, rotation=45, ha="right", margin={"t": 5}), |
| 72 | + axis_text_y=element_text(size=16, ha="right", margin={"r": 5}), |
69 | 73 | legend_title=element_text(size=16), |
70 | 74 | legend_text=element_text(size=14), |
| 75 | + legend_position="right", |
71 | 76 | panel_grid_major=element_blank(), |
72 | 77 | panel_grid_minor=element_blank(), |
| 78 | + panel_background=element_rect(fill="white"), |
| 79 | + plot_background=element_rect(fill="white"), |
73 | 80 | ) |
74 | 81 | ) |
75 | 82 |
|
|
0 commit comments