Skip to content

Instantly share code, notes, and snippets.

@tonyfast
Created August 19, 2021 00:26
Show Gist options
  • Save tonyfast/d01a0248979b21c9484d0827e04c0e68 to your computer and use it in GitHub Desktop.
Save tonyfast/d01a0248979b21c9484d0827e04c0e68 to your computer and use it in GitHub Desktop.
using templates to generate alt text for figures in matplotib
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "f1dd85ab-e176-4915-bf8a-79adf54f942d",
"metadata": {},
"source": [
"# generating alt text for an image from a dataframe.\n",
"\n",
"to share generated alt text we need to understand that both the plots and alt text are projections of a dataframe;\n",
"one in pure form and the other in pure typography. to generate an example scenario we need:\n",
"1. a dataframe\n",
"2. a plot of the dataframe\n",
"3. formatted text derived from the dataframe\n",
"\n",
"warning: the alt text in this example can be improve, please help me. i wanted to demonstrate an end to end workflow for generated alt text. \n",
"\n",
"consult with [chartability](https://chartability.fizz.studio/ \"a methodology for ensuring that data visualizations, systems, and interfaces are accessible\")."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "83b2c83c-ff70-4c71-a8cd-7f3bd2a4a1b7",
"metadata": {},
"outputs": [],
"source": [
" %matplotlib agg\n",
" import pandas, IPython.display as display, io, jinja2, base64"
]
},
{
"cell_type": "markdown",
"id": "312d441d-0c83-4c2b-9c75-23b833d34f2b",
"metadata": {},
"source": [
"create some sample data `df`"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "60e47590-5c96-4575-b5e5-433dfd6ae9a8",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/tonyfast/miniforge3/lib/python3.9/site-packages/pandas/util/__init__.py:15: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.\n",
" import pandas.util.testing\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>DeWbsEAqVl</th>\n",
" <th>u7Shqke0mg</th>\n",
" <th>DNIa9Ydxjh</th>\n",
" <th>JhBydInTBG</th>\n",
" <th>QzFCquTMgL</th>\n",
" <th>iiTLaCjbvK</th>\n",
" <th>eTJR8I4inM</th>\n",
" <th>VeRukIzX7j</th>\n",
" <th>3t3PjjOxRt</th>\n",
" <th>7uNCtGznIg</th>\n",
" <th>...</th>\n",
" <th>ZWDCUmkC9H</th>\n",
" <th>SKxnmjbznW</th>\n",
" <th>OJZQgDldhm</th>\n",
" <th>d8jXEUjVX1</th>\n",
" <th>zZwmXOGn2R</th>\n",
" <th>itPeesfNjT</th>\n",
" <th>nCUaPaX4hN</th>\n",
" <th>7XYLZeOtEn</th>\n",
" <th>7eun8Zwowd</th>\n",
" <th>bvKwo0nVBO</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>A</th>\n",
" <td>-0.513266</td>\n",
" <td>-0.569885</td>\n",
" <td>1.046707</td>\n",
" <td>-0.040230</td>\n",
" <td>0.252344</td>\n",
" <td>-0.869195</td>\n",
" <td>0.400589</td>\n",
" <td>1.186798</td>\n",
" <td>1.121367</td>\n",
" <td>0.379662</td>\n",
" <td>...</td>\n",
" <td>-0.295613</td>\n",
" <td>-0.130283</td>\n",
" <td>1.396725</td>\n",
" <td>1.436834</td>\n",
" <td>-0.376181</td>\n",
" <td>0.083873</td>\n",
" <td>0.432758</td>\n",
" <td>0.569672</td>\n",
" <td>1.730417</td>\n",
" <td>-0.608284</td>\n",
" </tr>\n",
" <tr>\n",
" <th>B</th>\n",
" <td>-0.053815</td>\n",
" <td>1.635761</td>\n",
" <td>0.236135</td>\n",
" <td>0.674369</td>\n",
" <td>0.299866</td>\n",
" <td>-0.743593</td>\n",
" <td>1.655680</td>\n",
" <td>-0.240112</td>\n",
" <td>0.203308</td>\n",
" <td>1.455075</td>\n",
" <td>...</td>\n",
" <td>0.017701</td>\n",
" <td>-0.122268</td>\n",
" <td>-0.969117</td>\n",
" <td>-0.305535</td>\n",
" <td>-1.006477</td>\n",
" <td>-0.807684</td>\n",
" <td>-0.169746</td>\n",
" <td>1.277646</td>\n",
" <td>0.098450</td>\n",
" <td>-0.430554</td>\n",
" </tr>\n",
" <tr>\n",
" <th>C</th>\n",
" <td>-1.979477</td>\n",
" <td>0.762999</td>\n",
" <td>0.931630</td>\n",
" <td>-0.867674</td>\n",
" <td>1.146874</td>\n",
" <td>-0.828406</td>\n",
" <td>1.091406</td>\n",
" <td>-0.166953</td>\n",
" <td>-0.571468</td>\n",
" <td>2.372057</td>\n",
" <td>...</td>\n",
" <td>1.664442</td>\n",
" <td>0.899626</td>\n",
" <td>-1.266544</td>\n",
" <td>1.674116</td>\n",
" <td>-1.782052</td>\n",
" <td>-1.735131</td>\n",
" <td>0.320543</td>\n",
" <td>-0.457179</td>\n",
" <td>1.483902</td>\n",
" <td>0.120748</td>\n",
" </tr>\n",
" <tr>\n",
" <th>D</th>\n",
" <td>0.234598</td>\n",
" <td>-0.114717</td>\n",
" <td>-0.136272</td>\n",
" <td>-1.135210</td>\n",
" <td>0.606916</td>\n",
" <td>-0.102985</td>\n",
" <td>-0.614704</td>\n",
" <td>-1.935681</td>\n",
" <td>-0.640178</td>\n",
" <td>-0.397213</td>\n",
" <td>...</td>\n",
" <td>0.186925</td>\n",
" <td>-2.806571</td>\n",
" <td>0.806676</td>\n",
" <td>-0.019412</td>\n",
" <td>-0.824382</td>\n",
" <td>-1.037335</td>\n",
" <td>-1.542543</td>\n",
" <td>1.022760</td>\n",
" <td>-0.300296</td>\n",
" <td>0.441676</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>4 rows × 30 columns</p>\n",
"</div>"
],
"text/plain": [
" DeWbsEAqVl u7Shqke0mg DNIa9Ydxjh JhBydInTBG QzFCquTMgL iiTLaCjbvK \\\n",
"A -0.513266 -0.569885 1.046707 -0.040230 0.252344 -0.869195 \n",
"B -0.053815 1.635761 0.236135 0.674369 0.299866 -0.743593 \n",
"C -1.979477 0.762999 0.931630 -0.867674 1.146874 -0.828406 \n",
"D 0.234598 -0.114717 -0.136272 -1.135210 0.606916 -0.102985 \n",
"\n",
" eTJR8I4inM VeRukIzX7j 3t3PjjOxRt 7uNCtGznIg ... ZWDCUmkC9H \\\n",
"A 0.400589 1.186798 1.121367 0.379662 ... -0.295613 \n",
"B 1.655680 -0.240112 0.203308 1.455075 ... 0.017701 \n",
"C 1.091406 -0.166953 -0.571468 2.372057 ... 1.664442 \n",
"D -0.614704 -1.935681 -0.640178 -0.397213 ... 0.186925 \n",
"\n",
" SKxnmjbznW OJZQgDldhm d8jXEUjVX1 zZwmXOGn2R itPeesfNjT nCUaPaX4hN \\\n",
"A -0.130283 1.396725 1.436834 -0.376181 0.083873 0.432758 \n",
"B -0.122268 -0.969117 -0.305535 -1.006477 -0.807684 -0.169746 \n",
"C 0.899626 -1.266544 1.674116 -1.782052 -1.735131 0.320543 \n",
"D -2.806571 0.806676 -0.019412 -0.824382 -1.037335 -1.542543 \n",
"\n",
" 7XYLZeOtEn 7eun8Zwowd bvKwo0nVBO \n",
"A 0.569672 1.730417 -0.608284 \n",
"B 1.277646 0.098450 -0.430554 \n",
"C -0.457179 1.483902 0.120748 \n",
"D 1.022760 -0.300296 0.441676 \n",
"\n",
"[4 rows x 30 columns]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" df = pandas.util.testing.makeDataFrame(); df.T"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "e0e6f2dd-cdb3-4846-ba2c-40a35488044c",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>count</th>\n",
" <th>mean</th>\n",
" <th>std</th>\n",
" <th>min</th>\n",
" <th>25%</th>\n",
" <th>50%</th>\n",
" <th>75%</th>\n",
" <th>max</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>A</th>\n",
" <td>30.0</td>\n",
" <td>0.309370</td>\n",
" <td>0.864548</td>\n",
" <td>-0.891069</td>\n",
" <td>-0.356039</td>\n",
" <td>0.113096</td>\n",
" <td>1.033456</td>\n",
" <td>2.519034</td>\n",
" </tr>\n",
" <tr>\n",
" <th>B</th>\n",
" <td>30.0</td>\n",
" <td>0.119557</td>\n",
" <td>0.923898</td>\n",
" <td>-1.570313</td>\n",
" <td>-0.563011</td>\n",
" <td>0.055682</td>\n",
" <td>0.754481</td>\n",
" <td>1.752108</td>\n",
" </tr>\n",
" <tr>\n",
" <th>C</th>\n",
" <td>30.0</td>\n",
" <td>-0.007826</td>\n",
" <td>1.213352</td>\n",
" <td>-1.979477</td>\n",
" <td>-0.872796</td>\n",
" <td>0.052330</td>\n",
" <td>0.923629</td>\n",
" <td>2.372057</td>\n",
" </tr>\n",
" <tr>\n",
" <th>D</th>\n",
" <td>30.0</td>\n",
" <td>-0.505479</td>\n",
" <td>0.884101</td>\n",
" <td>-2.806571</td>\n",
" <td>-1.074367</td>\n",
" <td>-0.393693</td>\n",
" <td>0.135341</td>\n",
" <td>1.022760</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" count mean std min 25% 50% 75% max\n",
"A 30.0 0.309370 0.864548 -0.891069 -0.356039 0.113096 1.033456 2.519034\n",
"B 30.0 0.119557 0.923898 -1.570313 -0.563011 0.055682 0.754481 1.752108\n",
"C 30.0 -0.007826 1.213352 -1.979477 -0.872796 0.052330 0.923629 2.372057\n",
"D 30.0 -0.505479 0.884101 -2.806571 -1.074367 -0.393693 0.135341 1.022760"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" statistics = df.describe(); statistics.T"
]
},
{
"cell_type": "markdown",
"id": "0237333b-0413-463a-a7c7-a58154480714",
"metadata": {},
"source": [
"## about the data"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "ccbf698d-72bf-47a2-8ba0-45794305af51",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"`df` is a dataframe with 30 rows and 4 columns with the names A, B, C, D"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" display.Markdown(F\"`df` is a dataframe with {len(df)} rows and {len(df.columns)} columns with the names {', '.join(df.columns)}\")"
]
},
{
"cell_type": "markdown",
"id": "3257f61c-ef66-49d7-9104-149f64e8d5f5",
"metadata": {},
"source": [
"## capturing the `matplotlib` figure\n",
"\n",
"using `io.BytesIO` to read the figure from the pipe and for the image a base64 encoded [data uri](https://en.wikipedia.org/wiki/Data_URI_scheme \"data uri scheme wiki\"). this first example uses a `boxplot`"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "6ae4fc03-834c-47ae-b8f2-93f97167e08d",
"metadata": {},
"outputs": [],
"source": [
" data = io.BytesIO()\n",
" df.plot.box().figure.savefig(data)\n",
" image = F\"data:image/png;base64,{base64.b64encode(data.getvalue()).decode()}\""
]
},
{
"cell_type": "markdown",
"id": "ee8406b6-f208-4922-b761-fdfde259c231",
"metadata": {},
"source": [
"write a formatted string describing the `boxplot` figure."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "1b5365d4-26bc-422b-9191-05575869c615",
"metadata": {},
"outputs": [],
"source": [
" alt = F\"\"\"A box plot showing the columns with names {\", \".join(df.columns)}. The averages for each columns are: {\n",
" \", \".join(f'{k} is {v:.2f}' for k, v in statistics.loc['mean'].items())\n",
" }.\"\"\""
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "dfa2735f-318e-4ce4-90aa-e0a404d0349c",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"![](data:image/png;base64,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BDv2tf3ss8/GT37yk+js7IyPfvSjsXLlyjhy5EjR41EF3gqOUzY0NBTf+c534ne/+13s3r071q9fH7fffnvRY1FBpVIp5syZExERc+bMiU984hPx5je/Ofbu3RstLS0FT8dEuvHGG6OmpiY2bdoUDQ0No5+/+OKL44Mf/GCBk1EJ//61PW/evHjNa14Tr3/96+Otb31rrF+/Pm644YaCJ6TS7AByynp6euLCCy+MCy+8MN7znvfE/fffH15GMo/BwcF44IEHoqOjI84555yix2ECPf/887Fx48a46aabjou/Y17xildUfyiq7i1veUtccskl8eCDDxY9ClUgADll9957b7znPe+JiBcfPhgcHHRu0CS3YcOGaGxsjMbGxpgxY0Y89NBD0dPTE1Om+NYxmWzZsiVGRkbioosuKnoUCnbRRRfFs88+W/QYVIHv4pySzZs3x6ZNm+Laa6+NiIipU6fGqlWr4r777it4Miqps7Mzent7o7e3N37729/G8uXL48orr4y//vWvRY/GBDq2k19TU1PwJBRtZGTE/4MknAPIKbn33nvjyJEjMW/evNHPjYyMxLRp02L//v0xa9asAqejUhoaGqKjo2P0+pIlS6KpqSm+9rWvxac+9akCJ2MivfKVr4yampp45pln4uqrry56HAr0zDPPxKJFi4oegyqwA8h/dOTIkfjGN74Rn//850d3g3p7e+MPf/hDnH/++fHAAw8UPSJVUlNTE1OmTIkDBw4UPQoTaPbs2fGOd7wjvvzlL8fQ0NBL/vwf//hH9Yei6n7xi1/EU089Fddcc03Ro1AFdgD5jzZs2BD79++P66+/Ppqamo77s3e9611x7733xs0331zQdFRSuVyO3bt3R0TE/v3740tf+lIMDg7GVVddVfBkTLR77rknrrjiirj88svjk5/8ZLzqVa+KI0eOxMMPPxzr1q2LZ555pugRmUDHvraHh4fjb3/7W2zcuDG6u7tj5cqV8d73vrfo8agCAch/dO+998bb3va2l8RfRMQ111wTn/nMZ+LJJ5+M17zmNQVMRyVt3LgxzjvvvIiImDFjRlx00UXx3e9+N5YtW1bsYEy4RYsWxZNPPhmf/vSn42Mf+1js2rUrWlpaYsmSJbFu3bqix2OCHfvanjp1asyaNSsuueSS+OIXvxjve9/7PMkriZoRr+MBAJCKzAcASEYAAgAkIwABAJIRgAAAyQhAAIBkBCAAQDICEAAgGQEIAJCMAAQASEYAAgAkIwABAJIRgAAAyQhAAIBkBCAAQDICEAAgGQEIAJCMAAQASEYAAgAkIwABAJIRgAAAyQhAAIBkBCAAQDICEAAgGQEIAJCMAAQASEYAAgAkIwABAJIRgAAAyQhAAIBkBCAAQDICEAAgmf8Dt0OfJmbQT7QAAAAASUVORK5CYII= \"A box plot showing the columns with names A, B, C, D. The averages for each columns are: A is 0.31, B is 0.12, C is -0.01, D is -0.51.\")"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" display.Markdown(F\"\"\"![]({image} \"{alt}\")\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "8f944b44-4d06-4c7b-b171-0f52d311c536",
"metadata": {},
"source": [
"other figures with need different alt text, and `jinja2` will be the most powerful candidate for templating. we put these concepts together in another figure below."
]
},
{
"cell_type": "markdown",
"id": "4717a172-2e75-4e64-a690-d28968abe2e0",
"metadata": {},
"source": [
"`capture` the figure as a data uri"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b6dc4f34-4e74-4c61-9406-b2a254d8bd77",
"metadata": {},
"outputs": [],
"source": [
" def capture(figure):\n",
" buffer = io.BytesIO()\n",
" figure.savefig(buffer)\n",
" return F\"data:image/png;base64,{base64.b64encode(buffer.getvalue()).decode()}\""
]
},
{
"cell_type": "markdown",
"id": "a43ae6c0-374c-408a-ad21-28491c44c94b",
"metadata": {},
"source": [
"use a template for the alt text to make an `accessible` figure."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "13f6f5f5-4c94-4ed9-bb9d-8450f205d7c1",
"metadata": {},
"outputs": [],
"source": [
" def accessible(figure, template, **kwargs):\n",
" return display.Markdown(F\"\"\"![]({capture(figure)} \"{template.render(**globals(), **kwargs)}\")\"\"\")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "d94fae2f-747b-4b31-952a-0d44e14cbfc6",
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"![](data:image/png;base64,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LygoUHNzs5588kkVFhZGtM5Y49TrYSxMuB7WrVunjz76SP/1X/91xn2dfE2Eeh5MuCbsQAAMwbp163TbbbeNuk92dva4/uyMjAxJA//Sy8zMDLS3tbUN+Zef3UI9Dx999JH+/Oc/D9nW3t4+pu+UmZmpmTNnqra2dsy1RpvH41FCQsKQu1yj/T1mZGQMu//ZZ5+t6dOnR6zWSBrPeRjOggUL9Oqrr4a7vJjmxOshXJx0Paxfv16/+93vVF5ergsuuGDUfZ18TYzlPAzHSdeEXQiAIfB4PPJ4PBH5s3NycpSRkaEDBw4oPz9f0sBzVAcPHtQTTzwRkc8cr1DPQ0FBgXw+nz744APNnz9fkvSHP/xBPp9PCxcuDPnzOjo61NzcHBSMY9WkSZM0d+5cHThwQDfffHOg/cCBA7rpppuGPaagoEBvvfVWUNs777yjefPmKTExMaL1Rsp4zsNwqqqq4uLvPZyceD2EixOuB8uytH79eu3du1dlZWXKyck54zFOvCbGcx6G44RrwnY2DT5xrMbGRquqqsp69NFHrSlTplhVVVVWVVWVdeLEicA+eXl51htvvBF4//jjj1tut9t64403rI8//tgqLi62MjMzLb/fb8dXCIulS5dal19+uVVZWWlVVlZal112mXXjjTcG7XPqeThx4oT193//99ahQ4eshoYGq7S01CooKLC+853vxM15+Ld/+zcrMTHR2rlzp/Xpp59a9913nzV58mTr6NGjlmVZ1oMPPmitXLkysH99fb2VnJxs3X///dann35q7dy500pMTLT+4z/+w66vEBZjPQ+/+tWvrL1791pffPGF9cc//tF68MEHLUnWnj177PoKYXHixInAz78k6+mnn7aqqqqsxsZGy7LMuR7Geh6cej3cc889ltvttsrKyqyWlpbAq6enJ7CPCdfEeM6DU68JuxEAw2zVqlWWpCGv0tLSwD6SrF27dgXef/vtt9bPfvYzKyMjw0pKSrIKCwutjz/+OPrFh1FHR4f14x//2Jo6dao1depU68c//vGQIfynnoeenh6rqKjISk1NtRITE60LL7zQWrVqldXU1BT94ifg2WeftWbOnGlNmjTJuvLKK4OmNli1apV1zTXXBO1fVlZm5efnW5MmTbKys7Ot559/PsoVR8ZYzsMTTzxh/dVf/ZV1zjnnWOeff771ve99z9q3b58NVYfX4NQVp79WrVplWZY518NYz4NTr4fhzsHpvwtMuCbGcx6cek3YzWVZ//9EKQAAAIzANDAAAACGIQACAAAYhgAIAABgGAIgAACAYQiAAAAAhiEAAgAAGIYACAAAYBgCIAAAgGEIgABwmkOHDikhIUFLly61uxQAiAhWAgGA0/z0pz/VlClT9OKLL+rTTz/VhRdeaHdJABBW3AEEgFN0d3fr3//933XPPffoxhtv1Msvv2x3SQAQdgRAADjF66+/rry8POXl5eknP/mJdu3aJTpKADgNARAATrFz50795Cc/kSQtXbpUXV1d+s///E+bqwKA8OIZQAD4fzU1NZozZ47+9Kc/KT09XZK0bt06dXZ26re//a3N1QFA+JxtdwEAECt27typkydP6jvf+U6gzbIsJSYm6tixYzr//PNtrA4Awoc7gAAg6eTJk7rgggv0wAMPqKioKGjbLbfcovXr12vdunU2VQcA4UUABABJb775plasWKG2tja53e6gbQ8//LD279+vqqoqm6oDgPAiAAKApOXLl+vbb7/Vvn37hmz77//+b82dO1cffvihrrzyShuqA4DwIgACAAAYhmlgAAAADEMABAAAMAwBEAAAwDAEQAAAAMMQAAEAAAxDAAQAADAMARAAAMAwBEAAAADDEAABAAAMQwAEAAAwDAEQAADAMARAAAAAw/wfC5chNVJ4ih8AAAAASUVORK5CYII= \"A scatter plot comparing 30 points of A vs B.\")"
],
"text/plain": [
"<IPython.core.display.Markdown object>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" accessible(df.plot.scatter(*\"AB\").figure, jinja2.Template(\"A scatter plot comparing {{len(df)}} points of A vs B.\"), len=len)"
]
},
{
"cell_type": "markdown",
"id": "f0ec843b-194a-485b-bc6e-81101b464749",
"metadata": {},
"source": [
"These alt text examples are probably incomplete, but the goal was to demontrate templating alt text from generated data with `pandas` and `matplotlib`"
]
}
],
"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.9.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment