From 04d00952a10059d6c2c9ae62e35264a3259c4756 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Thu, 9 Apr 2026 10:33:22 +0200 Subject: [PATCH 1/4] Sample code for the article on Altair --- altair-python/README.md | 3 + altair-python/altair-python.ipynb | 699 ++++++++++++++++++ altair-python/scatter_basic.py | 23 + altair-python/scatter_connected.py | 40 + .../scatter_encoding_channels copy.py | 26 + altair-python/scatter_faceted.py | 27 + altair-python/steps.py | 19 + 7 files changed, 837 insertions(+) create mode 100644 altair-python/README.md create mode 100644 altair-python/altair-python.ipynb create mode 100644 altair-python/scatter_basic.py create mode 100644 altair-python/scatter_connected.py create mode 100644 altair-python/scatter_encoding_channels copy.py create mode 100644 altair-python/scatter_faceted.py create mode 100644 altair-python/steps.py diff --git a/altair-python/README.md b/altair-python/README.md new file mode 100644 index 0000000000..55f1953171 --- /dev/null +++ b/altair-python/README.md @@ -0,0 +1,3 @@ +# Altair: Declarative Charts With Python + +This folder provides the code examples for the Real Python tutorial [Altair: Declarative Charts With Python](https://realpython.com/altair-python/). diff --git a/altair-python/altair-python.ipynb b/altair-python/altair-python.ipynb new file mode 100644 index 0000000000..75607e60b9 --- /dev/null +++ b/altair-python/altair-python.ipynb @@ -0,0 +1,699 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7e0a276e-132b-4984-8c6a-9560eca313ac", + "metadata": {}, + "source": [ + "## Step Counts as a Bar Chart" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9047ab05-f289-4fca-af14-9c1f75bc953e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.Chart(...)" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import altair as alt\n", + "import pandas as pd\n", + "\n", + "steps = pd.DataFrame({\n", + " \"Day\": [\"1-Mon\", \"2-Tue\", \"3-Wed\", \"4-Thu\", \"5-Fri\", \"6-Sat\", \"7-Sun\"],\n", + " \"Steps\": [6200, 8400, 7100, 9800, 5500, 9870, 3769],\n", + "})\n", + "\n", + "weekly_steps = alt.Chart(steps).mark_bar().encode(\n", + " x=\"Day\",\n", + " y=\"Steps\",\n", + ")\n", + "weekly_steps" + ] + }, + { + "cell_type": "markdown", + "id": "2fd3412b-83ef-40d8-94bc-16422c97c59b", + "metadata": {}, + "source": [ + "## The `movies` Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8446e30e-7fd0-406e-89ff-b5fec360830f", + "metadata": {}, + "outputs": [], + "source": [ + "from altair.datasets import data\n", + "\n", + "movies = data.movies()\n", + "movies = movies.dropna(subset=[\n", + " \"Production Budget\", \"Worldwide Gross\",\n", + " \"IMDB Rating\", \"Major Genre\", \"MPAA Rating\",\n", + "])" + ] + }, + { + "cell_type": "markdown", + "id": "39c7c21e-9536-48bc-8bc9-c3da708c2eec", + "metadata": {}, + "source": [ + "## Basic Scatter Plot" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4e25ea99-ec0f-4797-bc6c-46ab3cb36b22", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.Chart(...)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scatter = alt.Chart(movies).mark_point().encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + ")\n", + "scatter" + ] + }, + { + "cell_type": "markdown", + "id": "62d51fc2-c1e2-4398-a0bb-e4ab3a656832", + "metadata": {}, + "source": [ + "## Scatter Plot With Color and Size Encoding Channels" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6a6f25c8-7514-42ba-ba40-b2fd3c263e35", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.Chart(...)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scatter = alt.Chart(movies).mark_point().encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " color=\"Major Genre:N\",\n", + " size=\"IMDB Rating:Q\",\n", + " tooltip=[\"Title:N\", \"IMDB Rating:Q\"],\n", + ")\n", + "scatter" + ] + }, + { + "cell_type": "markdown", + "id": "9ff6c75f-6ef6-4c9e-a058-f7fdaa98864f", + "metadata": {}, + "source": [ + "## Faceted Scatter Plot Split by MPAA Rating" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4d895cbb-463d-495f-aacf-cba27d2878dd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.Chart(...)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scatter = alt.Chart(movies).mark_point().encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " color=\"Major Genre:N\",\n", + " size=\"IMDB Rating:Q\",\n", + " tooltip=[\"Title:N\", \"IMDB Rating:Q\"],\n", + " column=\"MPAA Rating:O\",\n", + ")\n", + "scatter" + ] + }, + { + "cell_type": "markdown", + "id": "3d7de8c7-f8f6-4673-9bc2-321f216c486a", + "metadata": {}, + "source": [ + "## Basic Scatter Plot With Brush" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "260eb204-8fd3-4a68-877d-4c5471004da9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.Chart(...)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "brush = alt.selection_interval()\n", + "\n", + "scatter = alt.Chart(movies).mark_point().encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " color=(\n", + " alt.when(brush)\n", + " .then(\"Major Genre:N\")\n", + " .otherwise(alt.value(\"lightgray\"))\n", + " ),\n", + ").add_params(brush)\n", + "\n", + "scatter" + ] + }, + { + "cell_type": "markdown", + "id": "c98813a3-48c5-4f55-b0c8-78cb0e53573f", + "metadata": {}, + "source": [ + "## Scatter Plot Connexted With Bars Plot" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "eb3aef15-7e39-47ea-936a-3c02c80462ad", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.VConcatChart(...)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bars = alt.Chart(movies).mark_bar().encode(\n", + " x=\"mean(IMDB Rating):Q\",\n", + " y=\"Major Genre:N\",\n", + ").transform_filter(brush)\n", + "\n", + "scatter & bars" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6984104a-ff47-475c-a1b3-e84d5f81a6dd", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/altair-python/scatter_basic.py b/altair-python/scatter_basic.py new file mode 100644 index 0000000000..864c73b0cd --- /dev/null +++ b/altair-python/scatter_basic.py @@ -0,0 +1,23 @@ +import altair as alt +from altair.datasets import data + +movies = data.movies() +movies = movies.dropna( + subset=[ + "Production Budget", + "Worldwide Gross", + "IMDB Rating", + "Major Genre", + "MPAA Rating", + ] +) + +scatter = ( + alt.Chart(movies) + .mark_point() + .encode( + x="Production Budget:Q", + y="Worldwide Gross:Q", + ) +) +scatter diff --git a/altair-python/scatter_connected.py b/altair-python/scatter_connected.py new file mode 100644 index 0000000000..3ece2625da --- /dev/null +++ b/altair-python/scatter_connected.py @@ -0,0 +1,40 @@ +import altair as alt +from altair.datasets import data + +movies = data.movies() +movies = movies.dropna( + subset=[ + "Production Budget", + "Worldwide Gross", + "IMDB Rating", + "Major Genre", + "MPAA Rating", + ] +) + +brush = alt.selection_interval() + +scatter = ( + alt.Chart(movies) + .mark_point() + .encode( + x="Production Budget:Q", + y="Worldwide Gross:Q", + color=(alt.when(brush).then("Major Genre:N").otherwise(alt.value("lightgray"))), + ) + .add_params(brush) +) + +scatter + +bars = ( + alt.Chart(movies) + .mark_bar() + .encode( + x="mean(IMDB Rating):Q", + y="Major Genre:N", + ) + .transform_filter(brush) +) + +scatter & bars diff --git a/altair-python/scatter_encoding_channels copy.py b/altair-python/scatter_encoding_channels copy.py new file mode 100644 index 0000000000..a582b6f6bc --- /dev/null +++ b/altair-python/scatter_encoding_channels copy.py @@ -0,0 +1,26 @@ +import altair as alt +from altair.datasets import data + +movies = data.movies() +movies = movies.dropna( + subset=[ + "Production Budget", + "Worldwide Gross", + "IMDB Rating", + "Major Genre", + "MPAA Rating", + ] +) + +scatter = ( + alt.Chart(movies) + .mark_point() + .encode( + x="Production Budget:Q", + y="Worldwide Gross:Q", + color="Major Genre:N", + size="IMDB Rating:Q", + tooltip=["Title:N", "IMDB Rating:Q"], + ) +) +scatter diff --git a/altair-python/scatter_faceted.py b/altair-python/scatter_faceted.py new file mode 100644 index 0000000000..dc4621b47e --- /dev/null +++ b/altair-python/scatter_faceted.py @@ -0,0 +1,27 @@ +import altair as alt +from altair.datasets import data + +movies = data.movies() +movies = movies.dropna( + subset=[ + "Production Budget", + "Worldwide Gross", + "IMDB Rating", + "Major Genre", + "MPAA Rating", + ] +) + +scatter = ( + alt.Chart(movies) + .mark_point() + .encode( + x="Production Budget:Q", + y="Worldwide Gross:Q", + color="Major Genre:N", + size="IMDB Rating:Q", + tooltip=["Title:N", "IMDB Rating:Q"], + column="MPAA Rating:O", + ) +) +scatter diff --git a/altair-python/steps.py b/altair-python/steps.py new file mode 100644 index 0000000000..102f2f49e3 --- /dev/null +++ b/altair-python/steps.py @@ -0,0 +1,19 @@ +import altair as alt +import pandas as pd + +steps = pd.DataFrame( + { + "Day": ["1-Mon", "2-Tue", "3-Wed", "4-Thu", "5-Fri", "6-Sat", "7-Sun"], + "Steps": [6200, 8400, 7100, 9800, 5500, 9870, 3769], + } +) + +weekly_steps = ( + alt.Chart(steps) + .mark_bar() + .encode( + x="Day", + y="Steps", + ) +) +weekly_steps From 2a73d835e101ea24214a555d6e7993c8a795db3a Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Thu, 9 Apr 2026 10:37:27 +0200 Subject: [PATCH 2/4] Fix Linter issues --- altair-python/scatter_connected.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/altair-python/scatter_connected.py b/altair-python/scatter_connected.py index 3ece2625da..9b767de435 100644 --- a/altair-python/scatter_connected.py +++ b/altair-python/scatter_connected.py @@ -20,7 +20,11 @@ .encode( x="Production Budget:Q", y="Worldwide Gross:Q", - color=(alt.when(brush).then("Major Genre:N").otherwise(alt.value("lightgray"))), + color=( + alt.when(brush) + .then("Major Genre:N") + .otherwise(alt.value("lightgray")), + ), ) .add_params(brush) ) From 47f94c91fd7efe04edba1dd1a033d0c4d4e92ae9 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Thu, 9 Apr 2026 10:51:16 +0200 Subject: [PATCH 3/4] More fixes --- altair-python/altair-python.ipynb | 113 +++++++++++------- ...s copy.py => scatter_encoding_channels.py} | 0 2 files changed, 73 insertions(+), 40 deletions(-) rename altair-python/{scatter_encoding_channels copy.py => scatter_encoding_channels.py} (100%) diff --git a/altair-python/altair-python.ipynb b/altair-python/altair-python.ipynb index 75607e60b9..476655994e 100644 --- a/altair-python/altair-python.ipynb +++ b/altair-python/altair-python.ipynb @@ -99,14 +99,20 @@ "import altair as alt\n", "import pandas as pd\n", "\n", - "steps = pd.DataFrame({\n", - " \"Day\": [\"1-Mon\", \"2-Tue\", \"3-Wed\", \"4-Thu\", \"5-Fri\", \"6-Sat\", \"7-Sun\"],\n", - " \"Steps\": [6200, 8400, 7100, 9800, 5500, 9870, 3769],\n", - "})\n", + "steps = pd.DataFrame(\n", + " {\n", + " \"Day\": [\"1-Mon\", \"2-Tue\", \"3-Wed\", \"4-Thu\", \"5-Fri\", \"6-Sat\", \"7-Sun\"],\n", + " \"Steps\": [6200, 8400, 7100, 9800, 5500, 9870, 3769],\n", + " }\n", + ")\n", "\n", - "weekly_steps = alt.Chart(steps).mark_bar().encode(\n", - " x=\"Day\",\n", - " y=\"Steps\",\n", + "weekly_steps = (\n", + " alt.Chart(steps)\n", + " .mark_bar()\n", + " .encode(\n", + " x=\"Day\",\n", + " y=\"Steps\",\n", + " )\n", ")\n", "weekly_steps" ] @@ -129,10 +135,15 @@ "from altair.datasets import data\n", "\n", "movies = data.movies()\n", - "movies = movies.dropna(subset=[\n", - " \"Production Budget\", \"Worldwide Gross\",\n", - " \"IMDB Rating\", \"Major Genre\", \"MPAA Rating\",\n", - "])" + "movies = movies.dropna(\n", + " subset=[\n", + " \"Production Budget\",\n", + " \"Worldwide Gross\",\n", + " \"IMDB Rating\",\n", + " \"Major Genre\",\n", + " \"MPAA Rating\",\n", + " ]\n", + ")" ] }, { @@ -231,9 +242,13 @@ } ], "source": [ - "scatter = alt.Chart(movies).mark_point().encode(\n", - " x=\"Production Budget:Q\",\n", - " y=\"Worldwide Gross:Q\",\n", + "scatter = (\n", + " alt.Chart(movies)\n", + " .mark_point()\n", + " .encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " )\n", ")\n", "scatter" ] @@ -334,12 +349,16 @@ } ], "source": [ - "scatter = alt.Chart(movies).mark_point().encode(\n", - " x=\"Production Budget:Q\",\n", - " y=\"Worldwide Gross:Q\",\n", - " color=\"Major Genre:N\",\n", - " size=\"IMDB Rating:Q\",\n", - " tooltip=[\"Title:N\", \"IMDB Rating:Q\"],\n", + "scatter = (\n", + " alt.Chart(movies)\n", + " .mark_point()\n", + " .encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " color=\"Major Genre:N\",\n", + " size=\"IMDB Rating:Q\",\n", + " tooltip=[\"Title:N\", \"IMDB Rating:Q\"],\n", + " )\n", ")\n", "scatter" ] @@ -440,13 +459,17 @@ } ], "source": [ - "scatter = alt.Chart(movies).mark_point().encode(\n", - " x=\"Production Budget:Q\",\n", - " y=\"Worldwide Gross:Q\",\n", - " color=\"Major Genre:N\",\n", - " size=\"IMDB Rating:Q\",\n", - " tooltip=[\"Title:N\", \"IMDB Rating:Q\"],\n", - " column=\"MPAA Rating:O\",\n", + "scatter = (\n", + " alt.Chart(movies)\n", + " .mark_point()\n", + " .encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " color=\"Major Genre:N\",\n", + " size=\"IMDB Rating:Q\",\n", + " tooltip=[\"Title:N\", \"IMDB Rating:Q\"],\n", + " column=\"MPAA Rating:O\",\n", + " )\n", ")\n", "scatter" ] @@ -549,15 +572,20 @@ "source": [ "brush = alt.selection_interval()\n", "\n", - "scatter = alt.Chart(movies).mark_point().encode(\n", - " x=\"Production Budget:Q\",\n", - " y=\"Worldwide Gross:Q\",\n", - " color=(\n", - " alt.when(brush)\n", - " .then(\"Major Genre:N\")\n", - " .otherwise(alt.value(\"lightgray\"))\n", - " ),\n", - ").add_params(brush)\n", + "scatter = (\n", + " alt.Chart(movies)\n", + " .mark_point()\n", + " .encode(\n", + " x=\"Production Budget:Q\",\n", + " y=\"Worldwide Gross:Q\",\n", + " color=(\n", + " alt.when(brush)\n", + " .then(\"Major Genre:N\")\n", + " .otherwise(alt.value(\"lightgray\"))\n", + " ),\n", + " )\n", + " .add_params(brush)\n", + ")\n", "\n", "scatter" ] @@ -658,10 +686,15 @@ } ], "source": [ - "bars = alt.Chart(movies).mark_bar().encode(\n", - " x=\"mean(IMDB Rating):Q\",\n", - " y=\"Major Genre:N\",\n", - ").transform_filter(brush)\n", + "bars = (\n", + " alt.Chart(movies)\n", + " .mark_bar()\n", + " .encode(\n", + " x=\"mean(IMDB Rating):Q\",\n", + " y=\"Major Genre:N\",\n", + " )\n", + " .transform_filter(brush)\n", + ")\n", "\n", "scatter & bars" ] diff --git a/altair-python/scatter_encoding_channels copy.py b/altair-python/scatter_encoding_channels.py similarity index 100% rename from altair-python/scatter_encoding_channels copy.py rename to altair-python/scatter_encoding_channels.py From 791a866f64450283ef5b7de78a904eff9d8024b3 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Thu, 9 Apr 2026 10:56:06 +0200 Subject: [PATCH 4/4] More fixes --- altair-python/scatter_basic.py | 3 --- altair-python/scatter_connected.py | 1 - altair-python/scatter_encoding_channels.py | 1 - 3 files changed, 5 deletions(-) diff --git a/altair-python/scatter_basic.py b/altair-python/scatter_basic.py index 864c73b0cd..0f798cbed4 100644 --- a/altair-python/scatter_basic.py +++ b/altair-python/scatter_basic.py @@ -6,9 +6,6 @@ subset=[ "Production Budget", "Worldwide Gross", - "IMDB Rating", - "Major Genre", - "MPAA Rating", ] ) diff --git a/altair-python/scatter_connected.py b/altair-python/scatter_connected.py index 9b767de435..a43cb069c6 100644 --- a/altair-python/scatter_connected.py +++ b/altair-python/scatter_connected.py @@ -8,7 +8,6 @@ "Worldwide Gross", "IMDB Rating", "Major Genre", - "MPAA Rating", ] ) diff --git a/altair-python/scatter_encoding_channels.py b/altair-python/scatter_encoding_channels.py index a582b6f6bc..f815e4278e 100644 --- a/altair-python/scatter_encoding_channels.py +++ b/altair-python/scatter_encoding_channels.py @@ -8,7 +8,6 @@ "Worldwide Gross", "IMDB Rating", "Major Genre", - "MPAA Rating", ] )