Skip to content

ratios in numerical columns¤

there is an interesting outcome when table cells have access to their --ratio in the distribution available in css. these values make it possible to use visual forms to identify colors. it is potentially an axis of design to experiment to design for low numeracy.

%%
{{table._repr_html_()}}

    gists = (await (
        "https://api.github.com/users/tonyfast/gists?page=" + pandas.RangeIndex(1, 3).astype(str)
    ).http.get()).explode().series().set_index("id")
    gists.index.name = "gist_id"
we're going to quickly make a table of my gist from github.

    files = gists.join(gists.files.apply(dict.values).apply(list).explode().series())
unravel all the gists in each gist payload.

    time = files.columns[files.columns.str.endswith("_at")].tolist()
    files[time] = files[time].apply(pandas.to_datetime, axis=1)
    files = files.assign(timespan=files.updated_at - files.created_at)

convert times to their proper types and substract them so out dataframe 
contains integers, datetimes, and timedeltas, types with numerical representations.

    files[cat] = files[cat := "language type".split()].astype("category")
    df = files[time + "timespan filename description language type size".split()]

now are going to add a few lines of `css` that uses the `--ratio` variables in each numerical cell
to produce visual representation of the cell value in the larger distribution.
it is really interesting how we start to create the cell border form when we do this.
at a glance we can visually observe relative positions of values in a column.
further, scrolling creates really interesting movement that provides user controlled animation.

    display\
```css
td {
    --marker-width: .2ch;
    background: linear-gradient(90deg, 
                                rgba(255, 0, 0, 0) 0% calc(var(--ratio) * 100% - var(--marker-width)),
                                rgba(255, 0, 0, 1) calc(var(--ratio) * 100% - var(--marker-width)) calc(var(--ratio) * 100% + var(--marker-width)),
                                rgba(255, 0, 0, 0) calc(var(--ratio) * 100% + var(--marker-width)) 100%
                               ),
                linear-gradient(0deg, 
                                rgba(255, 0, 0, 0) 0% calc(var(--ratio) * 100% - var(--marker-width)),
                                rgba(255, 0, 0, 1) calc(var(--ratio) * 100% - var(--marker-width)) calc(var(--ratio) * 100% + var(--marker-width)),
                                rgba(255, 0, 0, 0) calc(var(--ratio) * 100% + var(--marker-width)) 100%
                               ); 
}
```

    notebooks = (
        await files[files.language.eq("Jupyter Notebook")].raw_url.http.get()
    ).apply(json.loads).series()
read the `notebooks` and separate out the cells, outputs, and display objects.

    cells = notebooks.cells.enumerate("cell").series()
    outputs = cells.outputs[cells.outputs.fillna("").astype(bool)].enumerate("display").series()
    display_data = outputs['data'].dropna().series()

    df = (df.join(cells.groupby("gist_id").id.count().rename("cells"))
          .join(outputs.groupby("gist_id")["data"].count().rename("outputs")))
    import nbconvert_a11y.table
    table = df.sort_values("created_at", ascending=False).table(id="gist")
gist_id created_at updated_at timespan filename description language type size cells outputs
90c41d4994f75c594db804aeba56fc26 first_and_second_laws_of_thermodynamics.ipynb a notebook with revised literate pidgy cells for the first part of thermodyamics course Jupyter Notebook text/plain 20469 16.0 7.0
aa3b16c5a284150e3d727a843b6cefec axe_types.py Python application/x-python 8442 nan nan
713ae6c57602c0f85d011421b20d5ea0 BinaryExamples.ipynb a revision of a pycalphad documentation page as literate program. Jupyter Notebook text/plain 352154 0.0 6.0
c004044b4fe641735031ecf2069cf595 aom.json an exported accessibility tree from https://iota-school.github.io/notebooks-for-all/branch/extent/exports/html/lorenz-executed-smol.html#14 JSON application/json 52330 nan nan
e17946facd998a931527467d646cc822 README.md extensible notebook schemas Markdown text/markdown 3044 nan nan
99303420edc6021bbeeaa96c522469a1 ummm.py Python application/x-python 266 nan nan
c8e19ffb2b85f5bf6f5a4b6e76c327cd abc.py abc of python modules Python application/x-python 469 nan nan
4e33098a9f3a50805ad99d08e96825a6 graph shit.py Python application/x-python 4213 nan nan
243d7758d659c406f6e12cbd7b045384 hide_empty_outputs.html a selection to hide empty jupyterlab output cells HTML text/html 90 nan nan
42612252e0ed0df02f811932becd8241 2022-12-01-1.ipynb Jupyter Notebook text/plain 4956 8.0 0.0
abc7748fcc84177b59156d156132aabb lua.py Python application/x-python 408 nan nan
d9842e69957895a883203101d32053c5 2022-09-18-static-notebook-tags.ipynb Jupyter Notebook text/plain 21687 16.0 13.0
d3aa6592100eb30d7ec9efcb3b3efb06 details-summary.ipynb using two html standards to hide notebook content Jupyter Notebook text/plain 5841 8.0 1.0
146153f37825c9a0d078027c141823c5 2022-08-05-iris-demo.ipynb a notebook demo'ing pandas/sklearn Jupyter Notebook text/plain 103473 14.0 12.0
ef00eeb40ce268ff68cc7d606437ac6c nbval triggers text/plain 84 nan nan
1172d78b9a9a9738c8be759d304220e4 2022-07-17-shebang-magic.ipynb make shebangs a cell magic Jupyter Notebook text/plain 9822 14.0 11.0
3006d326442a9f4dd2ba61370cc2d37e _snippet.py a json grammar to parse notebooks into source code Python application/x-python 1844 15.0 8.0
3006d326442a9f4dd2ba61370cc2d37e 2022-07-16-larknb.ipynb a json grammar to parse notebooks into source code Jupyter Notebook text/plain 19876 15.0 8.0
d8ed2e33c5f70ad3b8340d4cf6cace21 2022-07-16-list-of-urls-py-md.ipynb an essay on the interfaces between md & py using a list of urls Jupyter Notebook text/plain 16111 9.0 8.0
6c236af7dcaa87fc012f31b720575dd7 2022-06-28-.ipynb Jupyter Notebook text/plain 22890 11.0 9.0
1ddcdce4eab431a8227be352d4c5a57b 2021-12-15-a11y-highlights.md.ipynb 2021 a11y highlights Jupyter Notebook text/plain 446103 34.0 17.0
df99b18e240d43c8b966aeb0a6e5a0d8 2021-12-15-a11y-highlights.md.ipynb 2021 a11y highlights Jupyter Notebook text/plain 436488 34.0 3.0
4cec811eb02f0107dc77f7da564657a2 2021-12-15-a11y-highlights.md.ipynb 2021 a11y highlights Jupyter Notebook text/plain 446103 34.0 17.0
bec93ba06cb420d58db3b1a4656e05b7 2021-12-15-a11y-highlights.md.ipynb 2021 a11y highlights Jupyter Notebook text/plain 444956 32.0 16.0
121f22a609d142992bf081bda7a875f7 2021-10-13-gannt.ipynb making gannt charts with pandas Jupyter Notebook text/plain 111977 19.0 8.0
e2cae138e4bb043cd277709ff45ba8a3 2021-10-11-colorizing.ipynb learning about dataframes using color Jupyter Notebook text/plain 54416 25.0 7.0
f34f1fc4454de5e61b6ed55a6736071c 2021-10-08-distributions-dataframe.ipynb create a dataframe from your python distributions Jupyter Notebook text/plain 22674 21.0 7.0
0d5cbee1f3b4aac205e9ddd407d0f4dc 2021-10-03-pd-calendar.ipynb making calendars in pandas Jupyter Notebook text/plain 89667 43.0 11.0
0d5cbee1f3b4aac205e9ddd407d0f4dc requirements.txt making calendars in pandas Text text/plain 15 43.0 11.0
cf3a246202f177500d47146303bdc235 2021-10-01-drum-machine.ipynb the faker - sample data generator - drum machine Jupyter Notebook text/plain 3755 9.0 2.0
0035d132c0c9162de4b3e66e3d596334 suggest-changes-pr.ipynb a visual document showing how to suggest changes to code in github pull requests Jupyter Notebook text/plain 709746 12.0 nan
cbeb91729e94c785f6c50c6c434455f0 doit-requires.ipynb Jupyter Notebook text/plain 5494 12.0 2.0
bd97099fb9f932a6402e5c6161f14748 readme.md heres my description Markdown text/markdown 27 17.0 1.0
bd97099fb9f932a6402e5c6161f14748 arrays.ipynb heres my description Jupyter Notebook text/plain 4030 17.0 1.0
c040b39d6149ef4fa57343f073dbde38 publishing.ipynb Jupyter Notebook text/plain 4779 7.0 4.0
14e1115b6dd15e863326209c9492c327 ww-roles.ipynb Jupyter Notebook text/plain 7770 5.0 5.0
e7dd7ff3d808d57b77e9765626a73a91 testing-notebooks.md.ipynb a lesson on testing notebooks for part 3 of the writers workshop Jupyter Notebook text/plain 1399459 31.0 16.0
a9bb09cb019e201ed95b76a6f558a106 copy-pasta-trick.ipynb copy and paste images and attachments directly into markdown cells Jupyter Notebook text/plain 654769 5.0 nan
82e8b9744c139a63febb1a3280e91cec collection-ouputs.ipynb Jupyter Notebook text/plain 186568 23.0 5.0
82e8b9744c139a63febb1a3280e91cec gcal-sux.ipynb Jupyter Notebook text/plain 222588 23.0 5.0
82e8b9744c139a63febb1a3280e91cec pluck-attachments.ipynb Jupyter Notebook text/plain 4843 23.0 5.0
203fee00e29fadaaa0604e915eb7a8f6 readme.md notebooks about IPython mimetypes and mediatypes Markdown text/markdown 125 37.0 43.0
203fee00e29fadaaa0604e915eb7a8f6 requirements.txt notebooks about IPython mimetypes and mediatypes Text text/plain 297 37.0 43.0
203fee00e29fadaaa0604e915eb7a8f6 all-the-displays.md.ipynb notebooks about IPython mimetypes and mediatypes Jupyter Notebook text/plain 6664 37.0 43.0
203fee00e29fadaaa0604e915eb7a8f6 mimemediatypes.md.ipynb notebooks about IPython mimetypes and mediatypes Jupyter Notebook text/plain 653575 37.0 43.0
f53d109fffe1e46b90cd2da8ce322f45 hyper-collage.ipynb an essay on the inner and outside positions of computational notebooks with a practice exercise Jupyter Notebook text/plain 17544796 9.0 nan
5f17546e574531159c3ad6ecc889c45f modes.md.ipynb Jupyter Notebook text/plain 670642 4.0 1.0
053564797743b7fbbaa6e421fd2b059d emoji.md.ipynb Jupyter Notebook text/plain 50379 15.0 16.0
8f2e5f2afa1f85acdacef2a81a14e571 modes.md.ipynb Jupyter Notebook text/plain 669895 3.0 nan
2d356ded4dfe1ba263e829cb11c5dfc7 about-schema.ipynb Jupyter Notebook text/plain 31488 56.0 15.0
405e3ec4f800fbc9d2b0a142ef4d4b10 readme.md the utterances commenting system inside of the browser only jupyterlite interactive computing interface Markdown text/markdown 110 0.0 1.0
405e3ec4f800fbc9d2b0a142ef4d4b10 utterance.ipynb the utterances commenting system inside of the browser only jupyterlite interactive computing interface Jupyter Notebook text/plain 5950 0.0 1.0
04f2caed49085783037b6cf0ab24b84e rich-displays.ipynb Jupyter Notebook text/plain 44908 33.0 9.0
37a13eee3d0936013e393f3ffd83c90f outlining.ipynb Jupyter Notebook text/plain 7903 22.0 0.0
e4e11f53b34c957436d7f64319c8e05c outlining.ipynb Jupyter Notebook text/plain 7296 20.0 nan
16d3bc82d69890949212b46040bd86e1 embed-rdf.ipynb notebooks with rdf metadata Jupyter Notebook text/plain 13345 33.0 10.0
00cf40ccbddccca6b5eddb94bfcc6389 expand-compact-trivial.ipynb Jupyter Notebook text/plain 3006 13.0 1.0
eb60d7d650a6b4a6e626678a34465e66 gistsssss.ipynb Jupyter Notebook text/plain 73496 23.0 4.0
7a640121acfdea3f0e31b0bd9e243104 template-magic.ipynb Jupyter Notebook text/plain 9326 18.0 2.0
3440a5b4c19a257d6164fff93fbef154 magics.ipynb Jupyter Notebook text/plain 12759 24.0 6.0
min 15 0.0 0.0
max 17544796 56.0 43.0
controls

gists = (await (
    "https://api.github.com/users/tonyfast/gists?page=" + pandas.RangeIndex(1, 3).astype(str)
).http.get()).explode().series().set_index("id")
gists.index.name = "gist_id"

we're going to quickly make a table of my gist from github.

files = gists.join(gists.files.apply(dict.values).apply(list).explode().series())

unravel all the gists in each gist payload.

time = files.columns[files.columns.str.endswith("_at")].tolist()
files[time] = files[time].apply(pandas.to_datetime, axis=1)
files = files.assign(timespan=files.updated_at - files.created_at)

convert times to their proper types and substract them so out dataframe contains integers, datetimes, and timedeltas, types with numerical representations.

files[cat] = files[cat := "language type".split()].astype("category")
df = files[time + "timespan filename description language type size".split()]

now are going to add a few lines of css that uses the --ratio variables in each numerical cell to produce visual representation of the cell value in the larger distribution. it is really interesting how we start to create the cell border form when we do this. at a glance we can visually observe relative positions of values in a column. further, scrolling creates really interesting movement that provides user controlled animation.

display\
td {
    --marker-width: .2ch;
    background: linear-gradient(90deg, 
                                rgba(255, 0, 0, 0) 0% calc(var(--ratio) * 100% - var(--marker-width)),
                                rgba(255, 0, 0, 1) calc(var(--ratio) * 100% - var(--marker-width)) calc(var(--ratio) * 100% + var(--marker-width)),
                                rgba(255, 0, 0, 0) calc(var(--ratio) * 100% + var(--marker-width)) 100%
                               ),
                linear-gradient(0deg, 
                                rgba(255, 0, 0, 0) 0% calc(var(--ratio) * 100% - var(--marker-width)),
                                rgba(255, 0, 0, 1) calc(var(--ratio) * 100% - var(--marker-width)) calc(var(--ratio) * 100% + var(--marker-width)),
                                rgba(255, 0, 0, 0) calc(var(--ratio) * 100% + var(--marker-width)) 100%
                               ); 
}
notebooks = (
    await files[files.language.eq("Jupyter Notebook")].raw_url.http.get()
).apply(json.loads).series()

read the notebooks and separate out the cells, outputs, and display objects.

cells = notebooks.cells.enumerate("cell").series()
outputs = cells.outputs[cells.outputs.fillna("").astype(bool)].enumerate("display").series()
display_data = outputs['data'].dropna().series()

df = (df.join(cells.groupby("gist_id").id.count().rename("cells"))
      .join(outputs.groupby("gist_id")["data"].count().rename("outputs")))
import nbconvert_a11y.table
table = df.sort_values("created_at", ascending=False).table(id="gist")
  • the type row needs to get added
  • experiment with different cells markers and css gradients

marginalia¤

i added aria-sort annotations to the table and thought some css would give visual representation of the sortedness. add much context and information will facilitate an accessible experience dyscalculia.

th[aria-sort]::after {
    content: attr(aria-sort);
    font-weight: 100;
}