|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | heatmap-basic: Basic Heatmap |
3 | 3 | Library: altair 6.0.0 | Python 3.14.3 |
4 | 4 | Quality: 87/100 | Updated: 2026-02-15 |
|
9 | 9 | import pandas as pd |
10 | 10 |
|
11 | 11 |
|
12 | | -# Data - correlation matrix with realistic variables |
| 12 | +# Data - correlation matrix with realistic weather variables |
13 | 13 | np.random.seed(42) |
14 | 14 | variables = [ |
15 | 15 | "Temperature", |
|
28 | 28 | # Inject realistic correlations with stronger relationships |
29 | 29 | raw[:, 1] += raw[:, 0] * 0.6 # Humidity ~ Temperature |
30 | 30 | raw[:, 5] += raw[:, 1] * 0.7 # Cloud Cover ~ Humidity |
31 | | -raw[:, 6] += raw[:, 5] * 0.65 # Precipitation ~ Cloud Cover (stronger) |
32 | | -raw[:, 4] -= raw[:, 5] * 0.9 # Visibility inversely ~ Cloud Cover (stronger) |
33 | | -raw[:, 7] -= raw[:, 5] * 0.7 # UV Index inversely ~ Cloud Cover (stronger) |
| 31 | +raw[:, 6] += raw[:, 5] * 0.65 # Precipitation ~ Cloud Cover |
| 32 | +raw[:, 4] -= raw[:, 5] * 0.9 # Visibility inversely ~ Cloud Cover |
| 33 | +raw[:, 7] -= raw[:, 5] * 0.7 # UV Index inversely ~ Cloud Cover |
34 | 34 | raw[:, 7] += raw[:, 0] * 0.5 # UV Index ~ Temperature |
35 | | -raw[:, 3] -= raw[:, 0] * 0.4 # Pressure inversely ~ Temperature (stronger) |
| 35 | +raw[:, 3] -= raw[:, 0] * 0.4 # Pressure inversely ~ Temperature |
36 | 36 | raw[:, 2] += raw[:, 3] * 0.3 # Wind Speed ~ Pressure |
37 | 37 |
|
38 | 38 | corr = np.corrcoef(raw.T) |
39 | 39 |
|
40 | | -# Build long-form dataframe |
41 | | -records = [] |
42 | | -for i, row_var in enumerate(variables): |
43 | | - for j, col_var in enumerate(variables): |
44 | | - val = round(corr[i, j], 2) |
45 | | - records.append({"x": col_var, "y": row_var, "value": val, "abs_value": abs(val)}) |
46 | | - |
47 | | -df = pd.DataFrame(records) |
| 40 | +# Build long-form dataframe using list comprehension |
| 41 | +df = pd.DataFrame( |
| 42 | + [ |
| 43 | + {"Row": row_var, "Column": col_var, "value": round(corr[i, j], 2)} |
| 44 | + for i, row_var in enumerate(variables) |
| 45 | + for j, col_var in enumerate(variables) |
| 46 | + ] |
| 47 | +) |
48 | 48 |
|
49 | 49 | # Axis ordering |
50 | 50 | axis_order = list(variables) |
|
55 | 55 | .mark_rect(stroke="#ffffff", strokeWidth=1.5, cornerRadius=2) |
56 | 56 | .encode( |
57 | 57 | x=alt.X( |
58 | | - "x:N", |
59 | | - title="Weather Variable", |
60 | | - sort=axis_order, |
61 | | - axis=alt.Axis( |
62 | | - labelFontSize=16, labelAngle=-30, orient="top", titleFontSize=20, titlePadding=12, labelPadding=8 |
63 | | - ), |
64 | | - ), |
65 | | - y=alt.Y( |
66 | | - "y:N", |
67 | | - title="Weather Variable", |
| 58 | + "Column:N", |
| 59 | + title=None, |
68 | 60 | sort=axis_order, |
69 | | - axis=alt.Axis(labelFontSize=16, titleFontSize=20, titlePadding=12, labelPadding=8), |
| 61 | + axis=alt.Axis(labelFontSize=15, labelAngle=-35, orient="top", labelPadding=6), |
70 | 62 | ), |
| 63 | + y=alt.Y("Row:N", title=None, sort=axis_order, axis=alt.Axis(labelFontSize=15, labelPadding=6)), |
71 | 64 | color=alt.Color( |
72 | 65 | "value:Q", |
73 | 66 | scale=alt.Scale(scheme="blueorange", domain=[-1, 1], domainMid=0), |
74 | 67 | legend=alt.Legend( |
75 | 68 | title="Correlation", |
76 | | - titleFontSize=18, |
77 | | - labelFontSize=16, |
78 | | - gradientLength=350, |
79 | | - gradientThickness=18, |
80 | | - titlePadding=8, |
81 | | - offset=12, |
| 69 | + titleFontSize=16, |
| 70 | + labelFontSize=14, |
| 71 | + gradientLength=300, |
| 72 | + gradientThickness=16, |
| 73 | + titlePadding=6, |
| 74 | + offset=8, |
| 75 | + direction="vertical", |
82 | 76 | ), |
83 | 77 | ), |
84 | 78 | tooltip=[ |
85 | | - alt.Tooltip("x:N", title="Variable X"), |
86 | | - alt.Tooltip("y:N", title="Variable Y"), |
| 79 | + alt.Tooltip("Column:N", title="Column"), |
| 80 | + alt.Tooltip("Row:N", title="Row"), |
87 | 81 | alt.Tooltip("value:Q", title="Correlation", format=".2f"), |
88 | 82 | ], |
89 | 83 | ) |
90 | 84 | ) |
91 | 85 |
|
92 | 86 | # Highlight cells with strong correlations using thicker borders |
93 | 87 | highlight = ( |
94 | | - alt.Chart(df[df["abs_value"] >= 0.7]) |
95 | | - .mark_rect(stroke="#333333", strokeWidth=2.5, filled=False, cornerRadius=2) |
96 | | - .encode(x=alt.X("x:N", sort=axis_order), y=alt.Y("y:N", sort=axis_order)) |
| 88 | + alt.Chart(df) |
| 89 | + .transform_filter((alt.datum.value >= 0.7) | (alt.datum.value <= -0.7)) |
| 90 | + .mark_rect(stroke="#2a2a2a", strokeWidth=2.5, filled=False, cornerRadius=2) |
| 91 | + .encode(x=alt.X("Column:N", sort=axis_order), y=alt.Y("Row:N", sort=axis_order)) |
97 | 92 | ) |
98 | 93 |
|
99 | 94 | # Text annotations with adaptive color |
100 | 95 | text = ( |
101 | 96 | alt.Chart(df) |
102 | | - .mark_text(fontSize=16, fontWeight="bold") |
| 97 | + .mark_text(fontSize=15, fontWeight="bold") |
103 | 98 | .encode( |
104 | | - x=alt.X("x:N", sort=axis_order), |
105 | | - y=alt.Y("y:N", sort=axis_order), |
| 99 | + x=alt.X("Column:N", sort=axis_order), |
| 100 | + y=alt.Y("Row:N", sort=axis_order), |
106 | 101 | text=alt.Text("value:Q", format=".2f"), |
107 | 102 | color=alt.when((alt.datum.value > 0.55) | (alt.datum.value < -0.55)) |
108 | | - .then(alt.value("white")) |
| 103 | + .then(alt.value("#ffffff")) |
109 | 104 | .otherwise(alt.value("#333333")), |
110 | 105 | ) |
111 | 106 | ) |
112 | 107 |
|
113 | | -# Combine and configure |
| 108 | +# Combine layers and configure |
114 | 109 | chart = ( |
115 | 110 | (heatmap + highlight + text) |
116 | 111 | .properties( |
117 | | - width=1200, |
118 | | - height=1200, |
| 112 | + width=700, |
| 113 | + height=730, |
119 | 114 | title=alt.Title( |
120 | 115 | "heatmap-basic · altair · pyplots.ai", |
121 | 116 | subtitle="Pairwise Pearson correlation coefficients for 8 weather metrics", |
122 | | - fontSize=28, |
123 | | - subtitleFontSize=18, |
| 117 | + fontSize=26, |
| 118 | + subtitleFontSize=16, |
124 | 119 | subtitleColor="#666666", |
125 | 120 | anchor="start", |
126 | | - offset=20, |
| 121 | + offset=16, |
127 | 122 | ), |
| 123 | + padding={"left": 10, "right": 10, "top": 10, "bottom": 10}, |
128 | 124 | ) |
129 | 125 | .configure_axis(grid=False) |
130 | 126 | .configure_view(strokeWidth=0) |
131 | 127 | ) |
132 | 128 |
|
133 | 129 | # Save |
134 | | -chart.save("plot.png", scale_factor=3.0) |
| 130 | +chart.save("plot.png", scale_factor=4.0) |
135 | 131 | chart.save("plot.html") |
0 commit comments