From 6f21732b04fa011805f82fbf400f82b8747ff64a Mon Sep 17 00:00:00 2001 From: liamcrismani <35870151+liamcrismani@users.noreply.github.com> Date: Sun, 17 May 2026 15:36:02 +0100 Subject: [PATCH 1/6] add first draft --- matplotlib/01_why_matplotlib.py | 186 ++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 matplotlib/01_why_matplotlib.py diff --git a/matplotlib/01_why_matplotlib.py b/matplotlib/01_why_matplotlib.py new file mode 100644 index 0000000..14e7e89 --- /dev/null +++ b/matplotlib/01_why_matplotlib.py @@ -0,0 +1,186 @@ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "marimo", +# "matplotlib==3.10.3", +# "numpy==2.3.1", +# "pandas==2.3.0", +# "polars==1.31.0", +# "requests==2.32.4", +# ] +# /// + +import marimo + +__generated_with = "0.14.9" +app = marimo.App(width="medium") + + +@app.cell(hide_code=True) +def _(mo): + mo.md(r"""# Why matplotlib?""") + return + + +@app.cell(hide_code=True) +def _(mo): + mo.md( + """ + *An introduction to Matplotlib's place in the Python visualization ecosystem and its design philosophy.* + + + [matplotilb](https://matplotlib.org/) is an awesome Python data visualization library--it forms the backbone of several plotting libraries, it's incredibly well documented, and it supports everything from simple plots to complex and interactive graphs. In their own words: + + > "matplotlib makes easy things easy and hard things possible" + """ + ) + return + + +@app.cell +def _(): + import marimo as mo + import pandas as pd + import matplotlib.pyplot as plt + return mo, pd, plt + + +@app.cell +def _(mo): + mo.md( + """ + insert examples here + + + + ### Who uses matplotib? + Matplotlib is one of the python ecosystem's most widely used plotting libraries. It might be just *the* most popular. Matplotlib was part of the O.G. Swiss army knife of python data science, alongside Numpy, pandas, scipy, and scikit-learn. + + But you don't have to be a data scientist to work with Matplotlib. Analysts, Business Intelligence aficionados, and weekend hobbyists alike can all benefit from its extensive features. + + ### What about plotly, altair, and seaborn? + + Sure, there are some awesome new kids on the block, and they offer some amazing capabilities, sometimes extending on matplotlib itself. If you're data visualisation curious, you should check out the hvplot and plotly courses in marimo learn. If you're just getting started with data visualisation with Python, you can't go wrong with getting your feet wet with matplotlib. + + + ### When should I use matplotlib? + + matplotlib can be used for simple line, scatter, and bar charts, as well as statistical visualisations, choropleths, 3D plots, and more. matplotlib leverages python objects to nail the user experience with plots. You get a Figure, an Axes, and a cornucopia of functions and methods to spin up the chart you need. + + Use matplotlib when you: + - need reproducible charts + - want full control over a visual + - just want your chart to work, no frills + + + ### A taste of what plt can do with marimo + + Let's take a quick look at what matplotlib can do. + + #### Quick and easy data exploration + """ + ) + return + + +@app.cell +def _(plt): + plt.plot([1, 2, 3, 4]) + plt.ylabel("Some numbers") + plt.title("Basic line plot") + plt.show() + return + + +@app.cell +def _(pd): + climate_data = pd.read_csv( + 'https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv', + parse_dates=True, + index_col='date' + ) + climate_data + return (climate_data,) + + +@app.cell +def _(climate_data, plt): + _fig, _ax = plt.subplots(2, 1, sharex=True) + + _ax[0].plot( + climate_data.index, + climate_data['co2'] + ) + _ax[1].plot( + climate_data.index, + climate_data['relative_temp'] + ) + plt.show() + return + + +@app.cell +def _(mo): + mo.md("""#### 3d plots""") + return + + +@app.cell +def _(plt): + import numpy as np + + from matplotlib import cbook, cm + from matplotlib.colors import LightSource + + # Load and format data + dem = cbook.get_sample_data('jacksboro_fault_dem.npz') + z = dem['elevation'] + nrows, ncols = z.shape + x = np.linspace(dem['xmin'], dem['xmax'], ncols) + y = np.linspace(dem['ymin'], dem['ymax'], nrows) + x, y = np.meshgrid(x, y) + + region = np.s_[5:50, 5:50] + x, y, z = x[region], y[region], z[region] + + # Set up plot + _fig, _ax = plt.subplots(subplot_kw=dict(projection='3d')) + + ls = LightSource(270, 45) + # To use a custom hillshading mode, override the built-in shading and pass + # in the rgb colors of the shaded surface calculated from "shade". + rgb = ls.shade(z, cmap=cm.gist_earth, vert_exag=0.1, blend_mode='soft') + surf = _ax.plot_surface(x, y, z, rstride=1, cstride=1, facecolors=rgb, + linewidth=0, antialiased=False, shade=False) + + plt.show() + return + + +@app.cell +def _(mo): + mo.md( + """ + #### maps + + + #### infographics + + + ## learn more + check out the rest of the course to learn more + """ + ) + return + + +@app.cell +def _(plt): + plt.plot([1, 2, 3, 4]) + plt.ylabel('some numbers') + plt.show() + return + + +if __name__ == "__main__": + app.run() From 2f8f29c680214ba580b7db102534db1296afda74 Mon Sep 17 00:00:00 2001 From: liamcrismani <35870151+liamcrismani@users.noreply.github.com> Date: Sun, 17 May 2026 17:54:45 +0100 Subject: [PATCH 2/6] update draft --- matplotlib/01_why_matplotlib.py | 263 ++++++++++++++++++++++---------- 1 file changed, 181 insertions(+), 82 deletions(-) diff --git a/matplotlib/01_why_matplotlib.py b/matplotlib/01_why_matplotlib.py index 14e7e89..2119938 100644 --- a/matplotlib/01_why_matplotlib.py +++ b/matplotlib/01_why_matplotlib.py @@ -12,101 +12,87 @@ import marimo -__generated_with = "0.14.9" +__generated_with = "0.23.6" app = marimo.App(width="medium") @app.cell(hide_code=True) def _(mo): - mo.md(r"""# Why matplotlib?""") + mo.md(r""" + # Why matplotlib? + """) return @app.cell(hide_code=True) def _(mo): - mo.md( - """ + mo.md(""" *An introduction to Matplotlib's place in the Python visualization ecosystem and its design philosophy.* - [matplotilb](https://matplotlib.org/) is an awesome Python data visualization library--it forms the backbone of several plotting libraries, it's incredibly well documented, and it supports everything from simple plots to complex and interactive graphs. In their own words: + [matplotilb](https://matplotlib.org/) is an awesome Python data visualization library--it forms the backbone of several plotting libraries, it's incredibly well documented, and it supports everything from simple plots to complex and interactive graphs. In their own words: - > "matplotlib makes easy things easy and hard things possible" - """ - ) + /// admonition | "matplotlib makes easy things easy and hard things possible" + /// + """) return @app.cell def _(): import marimo as mo + import numpy as np import pandas as pd import matplotlib.pyplot as plt - return mo, pd, plt - - -@app.cell -def _(mo): - mo.md( - """ - insert examples here - - - - ### Who uses matplotib? - Matplotlib is one of the python ecosystem's most widely used plotting libraries. It might be just *the* most popular. Matplotlib was part of the O.G. Swiss army knife of python data science, alongside Numpy, pandas, scipy, and scikit-learn. - - But you don't have to be a data scientist to work with Matplotlib. Analysts, Business Intelligence aficionados, and weekend hobbyists alike can all benefit from its extensive features. - - ### What about plotly, altair, and seaborn? - - Sure, there are some awesome new kids on the block, and they offer some amazing capabilities, sometimes extending on matplotlib itself. If you're data visualisation curious, you should check out the hvplot and plotly courses in marimo learn. If you're just getting started with data visualisation with Python, you can't go wrong with getting your feet wet with matplotlib. - - - ### When should I use matplotlib? - - matplotlib can be used for simple line, scatter, and bar charts, as well as statistical visualisations, choropleths, 3D plots, and more. matplotlib leverages python objects to nail the user experience with plots. You get a Figure, an Axes, and a cornucopia of functions and methods to spin up the chart you need. - - Use matplotlib when you: - - need reproducible charts - - want full control over a visual - - just want your chart to work, no frills + from matplotlib import cbook, cm + from matplotlib.colors import LightSource + return LightSource, cbook, cm, mo, np, pd, plt - ### A taste of what plt can do with marimo - Let's take a quick look at what matplotlib can do. +@app.cell(hide_code=True) +def _(mo): + mo.md(r""" + ## Some examples + Here's some examples from the Matplotlib docs and across the web. - #### Quick and easy data exploration - """ - ) + Matplotlib offers a couple interfaces: one functional, one OOP. Let's take a look at the functional interface first: + """) return @app.cell def _(plt): + # 4 lines of code gets us a simple visual :) plt.plot([1, 2, 3, 4]) plt.ylabel("Some numbers") plt.title("Basic line plot") - plt.show() + # plt.gca() gets the current `Axes` + plt.gca() + return + + +@app.cell(hide_code=True) +def _(mo): + mo.md(r""" + Now let's take a look at the OOP interface: + """) return @app.cell -def _(pd): +def _(pd, plt): climate_data = pd.read_csv( - 'https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv', + "https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv", parse_dates=True, - index_col='date' + index_col="date", ) - climate_data - return (climate_data,) - -@app.cell -def _(climate_data, plt): + # plt.subplots returns a Figure and Axis object. + # here, we ask for 2 rows and one column that share an x-axis _fig, _ax = plt.subplots(2, 1, sharex=True) + # Data is plotted by indexing a row _ax[0].plot( climate_data.index, climate_data['co2'] @@ -115,70 +101,183 @@ def _(climate_data, plt): climate_data.index, climate_data['relative_temp'] ) - plt.show() - return + # Chart customisations must also be called on each index + # The axis annotation methods are different to the plt.plot() interface + _ax[0].set_title("Global rise in C02 and relative temperature") + _ax[0].set_ylabel("C02 (ppm)") + _ax[1].set_xlabel("Year") + _ax[1].set_ylabel("Relative temperature (°C)") -@app.cell -def _(mo): - mo.md("""#### 3d plots""") + # Return the Figure + _fig return -@app.cell -def _(plt): - import numpy as np +@app.cell(hide_code=True) +def _(mo): + mo.md(""" + ### 3d plots + Everybody thinks 3D plots are cool. Here's an example which is available from the marimo snippets pane: + """) + return - from matplotlib import cbook, cm - from matplotlib.colors import LightSource +@app.cell(hide_code=True) +def _(LightSource, cbook, cm, np, plt): # Load and format data dem = cbook.get_sample_data('jacksboro_fault_dem.npz') - z = dem['elevation'] - nrows, ncols = z.shape - x = np.linspace(dem['xmin'], dem['xmax'], ncols) - y = np.linspace(dem['ymin'], dem['ymax'], nrows) - x, y = np.meshgrid(x, y) + _z = dem['elevation'] + nrows, ncols = _z.shape + _x = np.linspace(dem['xmin'], dem['xmax'], ncols) + _y = np.linspace(dem['ymin'], dem['ymax'], nrows) + _x, _y = np.meshgrid(_x, _y) region = np.s_[5:50, 5:50] - x, y, z = x[region], y[region], z[region] + _x, _y, _z = _x[region], _y[region], _z[region] # Set up plot _fig, _ax = plt.subplots(subplot_kw=dict(projection='3d')) ls = LightSource(270, 45) + # To use a custom hillshading mode, override the built-in shading and pass # in the rgb colors of the shaded surface calculated from "shade". - rgb = ls.shade(z, cmap=cm.gist_earth, vert_exag=0.1, blend_mode='soft') - surf = _ax.plot_surface(x, y, z, rstride=1, cstride=1, facecolors=rgb, + rgb = ls.shade(_z, cmap=cm.gist_earth, vert_exag=0.1, blend_mode='soft') + surf = _ax.plot_surface(_x, _y, _z, rstride=1, cstride=1, facecolors=rgb, linewidth=0, antialiased=False, shade=False) - plt.show() + plt.gca() return @app.cell def _(mo): - mo.md( - """ - #### maps + mo.md(""" + ### maps + + ### infographics + """) + return - #### infographics +@app.cell(hide_code=True) +def _(mo): + mo.md(r""" + ## Adding Interactivity + Naturally, since we're using marimo we may want to add some interactivity to our matplotlib charts. - ## learn more - check out the rest of the course to learn more - """ - ) + Here's an example with some simple [sliders](https://docs.marimo.io/api/inputs/slider/#marimo.ui.slider): + """) return +@app.cell(hide_code=True) +def _(mo): + n_points = mo.ui.slider( + 20, + 100, + value=50, + label="Smoothness" + ) + n_points + return (n_points,) + + +@app.cell(hide_code=True) +def _(mo): + wave_length = mo.ui.slider( + 2, + 10, + value=5, + label="Wave length" + ) + wave_length + return (wave_length,) + + @app.cell -def _(plt): - plt.plot([1, 2, 3, 4]) - plt.ylabel('some numbers') - plt.show() +def _(n_points, np, plt, wave_length): + _x = np.linspace(0, wave_length.value * np.pi, n_points.value) + + plt.plot(_x, np.sin(_x)) + plt.title(f"Sine wave with {n_points.value} points") + plt.gca() + return + + +@app.cell(hide_code=True) +def _(mo): + mo.md(r""" + /// admonition | Marimo also supports using lasso and box selection tools! + + Use [`mo.ui.matplotlib`](https://docs.marimo.io/api/plotting/#marimo.ui.matplotlib) to make matplotlib plots reactive: select data on the frontend, then use the selection to filter your data in Python. + + /// + """) + return + + +@app.cell(hide_code=True) +def _(mo): + mo.md(r""" + ## Design philosophy + + ### Parts of a figure + + At the core of Matplotlib chart architecture are four objects: + * a `Figure` + * an `Axes` + * two or more `Axis` objects + * `Artists` + + The Axes are the individual sets of indices, starting with at least one X-axis and Y-axis. + + The Figure is where the Axes are contained. + """) + return + + +@app.cell(hide_code=True) +def _(mo): + mo.image( + src="https://matplotlib.org/stable/_images/anatomy.png", + alt="Parts of a Matplotlib figure", + width=500, + height=500, + caption="An example of a Matplotlib figure, with annotations for the different objects, artists, and code." + ) + return + + +@app.cell(hide_code=True) +def _(mo): + mo.md(r""" + ### Coding style + As we saw earlier, Matplotlib offers two* interfaces for graphing data: `pyplot`, the functional interface, and the object-oriented (OO) style. + + In Matplotlib documentation, you'll see a mix of both styles, with the OO style recommended in general, especially for complex graphs and reproducible behaviours. + + For quick interactive work, the pyplot interface may be preferred. + + For Marimo, + + + *There's also a third interface, to be used when embedding Matplotlib in GUI applications. + """) + return + + +@app.cell(hide_code=True) +def _(mo): + mo.md(""" + ## More + * Check out the rest of this Marimo Learn course + * Read the docs for marimo-specific considerations when working with matplotlib: https://docs.marimo.io/guides/working_with_data/plotting/ + * Read the [Matplotlib Quick Start Guide](https://matplotlib.org/stable/users/explain/quick_start.html) + * Search the marimo snippets list in the developer panel (`ctrl/cmd + j`) for a bunch of Matplotlib examples + """) return From fb0b79530d6fe5e1a524e90ad68459945f912fea Mon Sep 17 00:00:00 2001 From: liamcrismani <35870151+liamcrismani@users.noreply.github.com> Date: Sun, 17 May 2026 21:12:05 +0100 Subject: [PATCH 3/6] standardise spelling --- matplotlib/01_why_matplotlib.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/matplotlib/01_why_matplotlib.py b/matplotlib/01_why_matplotlib.py index 2119938..b9a1776 100644 --- a/matplotlib/01_why_matplotlib.py +++ b/matplotlib/01_why_matplotlib.py @@ -30,9 +30,9 @@ def _(mo): *An introduction to Matplotlib's place in the Python visualization ecosystem and its design philosophy.* - [matplotilb](https://matplotlib.org/) is an awesome Python data visualization library--it forms the backbone of several plotting libraries, it's incredibly well documented, and it supports everything from simple plots to complex and interactive graphs. In their own words: + [Matplotilb](https://matplotlib.org/) is an awesome Python data visualization library--it forms the backbone of several plotting libraries, it's incredibly well documented, and it supports everything from simple plots to complex and interactive graphs. In their own words: - /// admonition | "matplotlib makes easy things easy and hard things possible" + /// admonition | "Matplotlib makes easy things easy and hard things possible" /// """) return @@ -157,7 +157,6 @@ def _(mo): ### maps - ### infographics """) return @@ -166,7 +165,7 @@ def _(mo): def _(mo): mo.md(r""" ## Adding Interactivity - Naturally, since we're using marimo we may want to add some interactivity to our matplotlib charts. + Naturally, since we're using marimo we may want to add some interactivity to our Matplotlib charts. Here's an example with some simple [sliders](https://docs.marimo.io/api/inputs/slider/#marimo.ui.slider): """) From d8aa7149a3db6222a2b110f002ba548156570354 Mon Sep 17 00:00:00 2001 From: liamcrismani <35870151+liamcrismani@users.noreply.github.com> Date: Sun, 21 Jun 2026 17:37:50 +0100 Subject: [PATCH 4/6] Finish and add code fences --- matplotlib/01_why_matplotlib.py | 171 +++++++++++++++++++++++++++++--- 1 file changed, 158 insertions(+), 13 deletions(-) diff --git a/matplotlib/01_why_matplotlib.py b/matplotlib/01_why_matplotlib.py index b9a1776..15aad38 100644 --- a/matplotlib/01_why_matplotlib.py +++ b/matplotlib/01_why_matplotlib.py @@ -1,8 +1,11 @@ # /// script # requires-python = ">=3.12" # dependencies = [ +# "geodatasets==2026.5.1", +# "geopandas[all]==1.1.3", # "marimo", # "matplotlib==3.10.3", +# "mcp==1.28.0", # "numpy==2.3.1", # "pandas==2.3.0", # "polars==1.31.0", @@ -12,7 +15,7 @@ import marimo -__generated_with = "0.23.6" +__generated_with = "0.23.10" app = marimo.App(width="medium") @@ -38,6 +41,23 @@ def _(mo): return +@app.cell +def _(mo): + mo.md(r""" + ```python + import marimo as mo + import numpy as np + import pandas as pd + import matplotlib.pyplot as plt + from matplotlib import cbook, cm + from matplotlib.colors import LightSource + import geopandas + import geodatasets + ``` + """) + return + + @app.cell def _(): import marimo as mo @@ -46,8 +66,10 @@ def _(): import matplotlib.pyplot as plt from matplotlib import cbook, cm from matplotlib.colors import LightSource + import geopandas + import geodatasets - return LightSource, cbook, cm, mo, np, pd, plt + return LightSource, cbook, cm, geodatasets, geopandas, mo, np, pd, plt @app.cell(hide_code=True) @@ -57,17 +79,28 @@ def _(mo): Here's some examples from the Matplotlib docs and across the web. Matplotlib offers a couple interfaces: one functional, one OOP. Let's take a look at the functional interface first: + + ```python + # 4 lines of code get us a simple visual :) + plt.plot([1, 2, 3, 4]) + plt.ylabel("Some numbers") + plt.title("Basic line plot") + + # get the current `Axes` + plt.gca() + ``` """) return -@app.cell +@app.cell(hide_code=True) def _(plt): - # 4 lines of code gets us a simple visual :) + # 4 lines of code get us a simple visual :) plt.plot([1, 2, 3, 4]) plt.ylabel("Some numbers") plt.title("Basic line plot") - # plt.gca() gets the current `Axes` + + # get the current `Axes` plt.gca() return @@ -76,11 +109,43 @@ def _(plt): def _(mo): mo.md(r""" Now let's take a look at the OOP interface: + + ```python + climate_data = pd.read_csv( + "https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv", + parse_dates=True, + index_col="date", + ) + + # plt.subplots returns a Figure and Axis object. + # here, we ask for 2 rows and one column that share an x-axis + _fig, _ax = plt.subplots(2, 1, sharex=True) + + # Data is plotted by indexing a row + _ax[0].plot( + climate_data.index, + climate_data['co2'] + ) + _ax[1].plot( + climate_data.index, + climate_data['relative_temp'] + ) + + # Chart customisations must also be called on each index + # The axis annotation methods are different to the plt.plot() interface + _ax[0].set_title("Global rise in C02 and relative temperature") + _ax[0].set_ylabel("C02 (ppm)") + _ax[1].set_xlabel("Year") + _ax[1].set_ylabel("Relative temperature (°C)") + + # Return the Figure + _fig + ``` """) return -@app.cell +@app.cell(hide_code=True) def _(pd, plt): climate_data = pd.read_csv( "https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv", @@ -119,6 +184,32 @@ def _(mo): mo.md(""" ### 3d plots Everybody thinks 3D plots are cool. Here's an example which is available from the marimo snippets pane: + + ```python + # Load and format data + dem = cbook.get_sample_data('jacksboro_fault_dem.npz') + _z = dem['elevation'] + nrows, ncols = _z.shape + _x = np.linspace(dem['xmin'], dem['xmax'], ncols) + _y = np.linspace(dem['ymin'], dem['ymax'], nrows) + _x, _y = np.meshgrid(_x, _y) + + region = np.s_[5:50, 5:50] + _x, _y, _z = _x[region], _y[region], _z[region] + + # Set up plot + _fig, _ax = plt.subplots(subplot_kw=dict(projection='3d')) + + ls = LightSource(270, 45) + + # To use a custom hillshading mode, override the built-in shading and pass + # in the rgb colors of the shaded surface calculated from "shade". + rgb = ls.shade(_z, cmap=cm.gist_earth, vert_exag=0.1, blend_mode='soft') + surf = _ax.plot_surface(_x, _y, _z, rstride=1, cstride=1, facecolors=rgb, + linewidth=0, antialiased=False, shade=False) + + plt.gca() + ``` """) return @@ -151,16 +242,46 @@ def _(LightSource, cbook, cm, np, plt): return -@app.cell +@app.cell(hide_code=True) def _(mo): mo.md(""" - ### maps + ### Maps + + Making maps with matplotlib is easiest using the [`Geopandas`](https://geopandas.org/en/stable/docs/user_guide/mapping.html) library. Geopandas provides spatially enabled dataframes, with a `.plot()` method. Anything that can be used in the `pyplot` interface can generally be used with `GeoDataFrame.plot()` + + ```python + import geopandas + import geodatasets + + # Create a GeoDataFrame from example dataset + chicago = geopandas.read_file(geodatasets.get_path("geoda.chicago_commpop")) + # Plot a choropleth of population in 2010 + chicago.plot( + column="POP2010", + legend=True, + legend_kwds={"label": "Population in 2010", "orientation": "horizontal"}, + ) + ``` """) return +@app.cell(hide_code=True) +def _(geodatasets, geopandas): + # Create a GeoDataFrame from example dataset + chicago = geopandas.read_file(geodatasets.get_path("geoda.chicago_commpop")) + + # Plot a choropleth of population in 2010 + chicago.plot( + column="POP2010", + legend=True, + legend_kwds={"label": "Population in 2010", "orientation": "horizontal"}, + ) + return + + @app.cell(hide_code=True) def _(mo): mo.md(r""" @@ -222,7 +343,6 @@ def _(mo): def _(mo): mo.md(r""" ## Design philosophy - ### Parts of a figure At the core of Matplotlib chart architecture are four objects: @@ -231,9 +351,18 @@ def _(mo): * two or more `Axis` objects * `Artists` - The Axes are the individual sets of indices, starting with at least one X-axis and Y-axis. + All Axes objects are rendered on the Figure. + + The Axes are the individual sets of indices, starting with at least one X-axis and Y-axis. The Axes methods are the primary interface for configuring most parts of your plot. + + Axis objects provide ticks, tick labels, and scales for the data in the Axes. + + Everything visible on the Figure is an Artist. + + + **The canvas and the artist** - The Figure is where the Axes are contained. + When working with matplotlib, you can use this mental model: the Figure is the canvas, and everything drawn on it is done by artists (lines, text, spines, etc.). When the Figure is rendered, the Artists are drawn to the canvas. """) return @@ -256,12 +385,28 @@ def _(mo): ### Coding style As we saw earlier, Matplotlib offers two* interfaces for graphing data: `pyplot`, the functional interface, and the object-oriented (OO) style. - In Matplotlib documentation, you'll see a mix of both styles, with the OO style recommended in general, especially for complex graphs and reproducible behaviours. + In the Matplotlib documentation, you'll see a mix of both styles, with the OO style generally recommended, especially for complex graphs and reproducible behaviours. For quick interactive work, the pyplot interface may be preferred. - For Marimo, + For Marimo, you can use either, but be sure to return the Figure and Axes of the chart you want to see as the last expression in your cell, e.g. + + ```python + plt.plot([1, 2]) + # plt.gca() gets the current `Axes` + plt.gca() + ``` + + or + + ```python + fig, ax = plt.subplots() + + ax.plot([1, 2]) + ax + ``` + If you want to output the plot in the console area, use `plt.show()` or `fig.show()`. *There's also a third interface, to be used when embedding Matplotlib in GUI applications. """) From 84f1b16f22b23724a077b37353c20692bb96602c Mon Sep 17 00:00:00 2001 From: liamcrismani <35870151+liamcrismani@users.noreply.github.com> Date: Sun, 21 Jun 2026 17:50:38 +0100 Subject: [PATCH 5/6] Add readme --- matplotlib/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 matplotlib/README.md diff --git a/matplotlib/README.md b/matplotlib/README.md new file mode 100644 index 0000000..e69de29 From 5f9c877fb8b206d39ecc7ce7c83f285c9f56879e Mon Sep 17 00:00:00 2001 From: liamcrismani <35870151+liamcrismani@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:16:31 +0100 Subject: [PATCH 6/6] Add finished first draft matplotlib/01_why_matplotlib.py and README --- matplotlib/01_why_matplotlib.py | 122 +++----------------------------- matplotlib/README.md | 18 +++++ 2 files changed, 29 insertions(+), 111 deletions(-) diff --git a/matplotlib/01_why_matplotlib.py b/matplotlib/01_why_matplotlib.py index 15aad38..9197f0a 100644 --- a/matplotlib/01_why_matplotlib.py +++ b/matplotlib/01_why_matplotlib.py @@ -5,11 +5,8 @@ # "geopandas[all]==1.1.3", # "marimo", # "matplotlib==3.10.3", -# "mcp==1.28.0", # "numpy==2.3.1", -# "pandas==2.3.0", -# "polars==1.31.0", -# "requests==2.32.4", +# "pandas==2.3.0" # ] # /// @@ -33,7 +30,12 @@ def _(mo): *An introduction to Matplotlib's place in the Python visualization ecosystem and its design philosophy.* - [Matplotilb](https://matplotlib.org/) is an awesome Python data visualization library--it forms the backbone of several plotting libraries, it's incredibly well documented, and it supports everything from simple plots to complex and interactive graphs. In their own words: + Why [Matplotlib](https://matplotlib.org/)? Part of the original Swiss Army Knife of Python data science libraries, Matplotlib is Python's foundational data visualization package–and for good reason: + * It forms the backbone of several plotting libraries; + * it's incredibly well documented; + * it supports everything from simple plots to complex and interactive graphs. + + In their own words: /// admonition | "Matplotlib makes easy things easy and hard things possible" /// @@ -41,23 +43,6 @@ def _(mo): return -@app.cell -def _(mo): - mo.md(r""" - ```python - import marimo as mo - import numpy as np - import pandas as pd - import matplotlib.pyplot as plt - from matplotlib import cbook, cm - from matplotlib.colors import LightSource - import geopandas - import geodatasets - ``` - """) - return - - @app.cell def _(): import marimo as mo @@ -79,21 +64,11 @@ def _(mo): Here's some examples from the Matplotlib docs and across the web. Matplotlib offers a couple interfaces: one functional, one OOP. Let's take a look at the functional interface first: - - ```python - # 4 lines of code get us a simple visual :) - plt.plot([1, 2, 3, 4]) - plt.ylabel("Some numbers") - plt.title("Basic line plot") - - # get the current `Axes` - plt.gca() - ``` """) return -@app.cell(hide_code=True) +@app.cell() def _(plt): # 4 lines of code get us a simple visual :) plt.plot([1, 2, 3, 4]) @@ -109,43 +84,11 @@ def _(plt): def _(mo): mo.md(r""" Now let's take a look at the OOP interface: - - ```python - climate_data = pd.read_csv( - "https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv", - parse_dates=True, - index_col="date", - ) - - # plt.subplots returns a Figure and Axis object. - # here, we ask for 2 rows and one column that share an x-axis - _fig, _ax = plt.subplots(2, 1, sharex=True) - - # Data is plotted by indexing a row - _ax[0].plot( - climate_data.index, - climate_data['co2'] - ) - _ax[1].plot( - climate_data.index, - climate_data['relative_temp'] - ) - - # Chart customisations must also be called on each index - # The axis annotation methods are different to the plt.plot() interface - _ax[0].set_title("Global rise in C02 and relative temperature") - _ax[0].set_ylabel("C02 (ppm)") - _ax[1].set_xlabel("Year") - _ax[1].set_ylabel("Relative temperature (°C)") - - # Return the Figure - _fig - ``` """) return -@app.cell(hide_code=True) +@app.cell() def _(pd, plt): climate_data = pd.read_csv( "https://assets.datacamp.com/production/repositories/3634/datasets/411add3f8570d5adf891127fd64095020210711b/climate_change.csv", @@ -184,37 +127,11 @@ def _(mo): mo.md(""" ### 3d plots Everybody thinks 3D plots are cool. Here's an example which is available from the marimo snippets pane: - - ```python - # Load and format data - dem = cbook.get_sample_data('jacksboro_fault_dem.npz') - _z = dem['elevation'] - nrows, ncols = _z.shape - _x = np.linspace(dem['xmin'], dem['xmax'], ncols) - _y = np.linspace(dem['ymin'], dem['ymax'], nrows) - _x, _y = np.meshgrid(_x, _y) - - region = np.s_[5:50, 5:50] - _x, _y, _z = _x[region], _y[region], _z[region] - - # Set up plot - _fig, _ax = plt.subplots(subplot_kw=dict(projection='3d')) - - ls = LightSource(270, 45) - - # To use a custom hillshading mode, override the built-in shading and pass - # in the rgb colors of the shaded surface calculated from "shade". - rgb = ls.shade(_z, cmap=cm.gist_earth, vert_exag=0.1, blend_mode='soft') - surf = _ax.plot_surface(_x, _y, _z, rstride=1, cstride=1, facecolors=rgb, - linewidth=0, antialiased=False, shade=False) - - plt.gca() - ``` """) return -@app.cell(hide_code=True) +@app.cell() def _(LightSource, cbook, cm, np, plt): # Load and format data dem = cbook.get_sample_data('jacksboro_fault_dem.npz') @@ -248,27 +165,11 @@ def _(mo): ### Maps Making maps with matplotlib is easiest using the [`Geopandas`](https://geopandas.org/en/stable/docs/user_guide/mapping.html) library. Geopandas provides spatially enabled dataframes, with a `.plot()` method. Anything that can be used in the `pyplot` interface can generally be used with `GeoDataFrame.plot()` - - ```python - import geopandas - import geodatasets - - - # Create a GeoDataFrame from example dataset - chicago = geopandas.read_file(geodatasets.get_path("geoda.chicago_commpop")) - - # Plot a choropleth of population in 2010 - chicago.plot( - column="POP2010", - legend=True, - legend_kwds={"label": "Population in 2010", "orientation": "horizontal"}, - ) - ``` """) return -@app.cell(hide_code=True) +@app.cell() def _(geodatasets, geopandas): # Create a GeoDataFrame from example dataset chicago = geopandas.read_file(geodatasets.get_path("geoda.chicago_commpop")) @@ -406,7 +307,6 @@ def _(mo): ax ``` - If you want to output the plot in the console area, use `plt.show()` or `fig.show()`. *There's also a third interface, to be used when embedding Matplotlib in GUI applications. """) diff --git a/matplotlib/README.md b/matplotlib/README.md index e69de29..298ff9c 100644 --- a/matplotlib/README.md +++ b/matplotlib/README.md @@ -0,0 +1,18 @@ +--- +title: Learn Matplotlib +description: > + Learn the basics of data vizualisation in Python with the timeless Matplotlib +--- + +You can open and run these notebooks in [molab](https://molab.marimo.io), marimo's free hosted notebook platform. + +## Notebooks + +- [![Open in molab](https://marimo.io/molab-shield.svg)]() Why Matplotlib? + + +## Contributors + +Thanks to our notebook authors: + +* []()