Skip to content

html tables in figures¤

today we made our own html table using data created with a pandas dataframe. then we used css to create image like representations of the tables; we hint at a potential future where more data is included in the data document rather than lost in other media.

this work builds off of histograms suck and considering accessible visualization using HTML standards.

example images of our figures¤

a sine wave created from a table with 1.5 rotations

a sine wave created from a table with 110 rotations

%%
```css
:root {
    --width: 1000px;
    --height: 400px;
}
table[role=table]{
    display: block;
    position: relative;
    width: var(--width);
    height: var(--height);
    tbody {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: var(--width);
        height: var(--height);
        tr {
            display: unset;
            position: absolute;
            left: calc((var(--x) - var(--x-min)) / (var(--x-max) - var(--x-min)) * var(--width));
            top: calc((var(--y) - var(--y-min)) / (var(--y-max) - var(--y-min)) * var(--height));
            width: 1rem;
            height: 1rem;
            border-radius: 1rem;
            border: solid;
        }
    }

}


.visually-hidden {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}

```
:root {
    --width: 1000px;
    --height: 400px;
}
table[role=table]{
    display: block;
    position: relative;
    width: var(--width);
    height: var(--height);
    tbody {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: var(--width);
        height: var(--height);
        tr {
            display: unset;
            position: absolute;
            left: calc((var(--x) - var(--x-min)) / (var(--x-max) - var(--x-min)) * var(--width));
            top: calc((var(--y) - var(--y-min)) / (var(--y-max) - var(--y-min)) * var(--height));
            width: 1rem;
            height: 1rem;
            border-radius: 1rem;
            border: solid;
        }
    }

}


.visually-hidden {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
</style>
%%    
    table =\
{% set format="%.4f" %}
<table role="table" style="--x-min: {{df.x.min()}}; --y-min: {{df.y.min()}}; --z-min: {{df.z.min()}}; --x-max: {{df.x.max()}}; --y-max: {{df.y.max()}}; --z-max: {{df.z.max()}};">
<caption>a sin wave</caption>
<thead class="visually-hidden" role="rowgroup">
<tr>
<th>index</th><th>x</th><th>y</th><th>z</th>
</tr>
</thead>
<tbody role="rowgroup">{% for i, row in df.iterrows() %}
    <tr role="row" style="--index: {{loop.index}}; --x: {{row.x}}; --y: {{row.y}}; --z: {{row.z}}">
<th>{{loop.index}}</th><td>{{format % row.x}}</td><td>{{format % row.y}}</td><td>{{format % row.z}}</td>
</tr>
    {%- endfor %}</tbody>
</table>
<figure>
<figcaption>creating the dataframe</figcaption>

    inc = locals().setdefault("inc", 2) + 1
    df = pandas.concat([
        (x := Series(numpy.linspace(0, inc*numpy.pi, 201))).rename("x"), 
        x.apply(numpy.sin).rename("y"), x.apply(numpy.cos).rename("z")
    ], axis=1)

</figure>
<figure>
<figcaption>source code html</figcaption>

```html
{{table}}
```

</figure>
table =\
a sin wave
indexxyz
10.00000.00001.0000
20.04710.04710.9989
30.09420.09410.9956
40.14140.14090.9900
50.18850.18740.9823
60.23560.23340.9724
70.28270.27900.9603
80.32990.32390.9461
90.37700.36810.9298
100.42410.41150.9114
110.47120.45400.8910
120.51840.49550.8686
130.56550.53580.8443
140.61260.57500.8181
150.65970.61290.7902
160.70690.64940.7604
170.75400.68450.7290
180.80110.71810.6959
190.84820.75010.6613
200.89540.78040.6252
210.94250.80900.5878
220.98960.83580.5490
231.03670.86070.5090
241.08380.88380.4679
251.13100.90480.4258
261.17810.92390.3827
271.22520.94090.3387
281.27230.95580.2940
291.31950.96860.2487
301.36660.97920.2028
311.41370.98770.1564
321.46080.99400.1097
331.50800.99800.0628
341.55510.99990.0157
351.60220.9995-0.0314
361.64930.9969-0.0785
371.69650.9921-0.1253
381.74360.9851-0.1719
391.79070.9759-0.2181
401.83780.9646-0.2639
411.88500.9511-0.3090
421.93210.9354-0.3535
431.97920.9178-0.3971
442.02630.8980-0.4399
452.07350.8763-0.4818
462.12060.8526-0.5225
472.16770.8271-0.5621
482.21480.7997-0.6004
492.26190.7705-0.6374
502.30910.7396-0.6730
512.35620.7071-0.7071
522.40330.6730-0.7396
532.45040.6374-0.7705
542.49760.6004-0.7997
552.54470.5621-0.8271
562.59180.5225-0.8526
572.63890.4818-0.8763
582.68610.4399-0.8980
592.73320.3971-0.9178
602.78030.3535-0.9354
612.82740.3090-0.9511
622.87460.2639-0.9646
632.92170.2181-0.9759
642.96880.1719-0.9851
653.01590.1253-0.9921
663.06310.0785-0.9969
673.11020.0314-0.9995
683.1573-0.0157-0.9999
693.2044-0.0628-0.9980
703.2515-0.1097-0.9940
713.2987-0.1564-0.9877
723.3458-0.2028-0.9792
733.3929-0.2487-0.9686
743.4400-0.2940-0.9558
753.4872-0.3387-0.9409
763.5343-0.3827-0.9239
773.5814-0.4258-0.9048
783.6285-0.4679-0.8838
793.6757-0.5090-0.8607
803.7228-0.5490-0.8358
813.7699-0.5878-0.8090
823.8170-0.6252-0.7804
833.8642-0.6613-0.7501
843.9113-0.6959-0.7181
853.9584-0.7290-0.6845
864.0055-0.7604-0.6494
874.0527-0.7902-0.6129
884.0998-0.8181-0.5750
894.1469-0.8443-0.5358
904.1940-0.8686-0.4955
914.2412-0.8910-0.4540
924.2883-0.9114-0.4115
934.3354-0.9298-0.3681
944.3825-0.9461-0.3239
954.4296-0.9603-0.2790
964.4768-0.9724-0.2334
974.5239-0.9823-0.1874
984.5710-0.9900-0.1409
994.6181-0.9956-0.0941
1004.6653-0.9989-0.0471
1014.7124-1.0000-0.0000
1024.7595-0.99890.0471
1034.8066-0.99560.0941
1044.8538-0.99000.1409
1054.9009-0.98230.1874
1064.9480-0.97240.2334
1074.9951-0.96030.2790
1085.0423-0.94610.3239
1095.0894-0.92980.3681
1105.1365-0.91140.4115
1115.1836-0.89100.4540
1125.2308-0.86860.4955
1135.2779-0.84430.5358
1145.3250-0.81810.5750
1155.3721-0.79020.6129
1165.4192-0.76040.6494
1175.4664-0.72900.6845
1185.5135-0.69590.7181
1195.5606-0.66130.7501
1205.6077-0.62520.7804
1215.6549-0.58780.8090
1225.7020-0.54900.8358
1235.7491-0.50900.8607
1245.7962-0.46790.8838
1255.8434-0.42580.9048
1265.8905-0.38270.9239
1275.9376-0.33870.9409
1285.9847-0.29400.9558
1296.0319-0.24870.9686
1306.0790-0.20280.9792
1316.1261-0.15640.9877
1326.1732-0.10970.9940
1336.2204-0.06280.9980
1346.2675-0.01570.9999
1356.31460.03140.9995
1366.36170.07850.9969
1376.40880.12530.9921
1386.45600.17190.9851
1396.50310.21810.9759
1406.55020.26390.9646
1416.59730.30900.9511
1426.64450.35350.9354
1436.69160.39710.9178
1446.73870.43990.8980
1456.78580.48180.8763
1466.83300.52250.8526
1476.88010.56210.8271
1486.92720.60040.7997
1496.97430.63740.7705
1507.02150.67300.7396
1517.06860.70710.7071
1527.11570.73960.6730
1537.16280.77050.6374
1547.21000.79970.6004
1557.25710.82710.5621
1567.30420.85260.5225
1577.35130.87630.4818
1587.39850.89800.4399
1597.44560.91780.3971
1607.49270.93540.3535
1617.53980.95110.3090
1627.58690.96460.2639
1637.63410.97590.2181
1647.68120.98510.1719
1657.72830.99210.1253
1667.77540.99690.0785
1677.82260.99950.0314
1687.86970.9999-0.0157
1697.91680.9980-0.0628
1707.96390.9940-0.1097
1718.01110.9877-0.1564
1728.05820.9792-0.2028
1738.10530.9686-0.2487
1748.15240.9558-0.2940
1758.19960.9409-0.3387
1768.24670.9239-0.3827
1778.29380.9048-0.4258
1788.34090.8838-0.4679
1798.38810.8607-0.5090
1808.43520.8358-0.5490
1818.48230.8090-0.5878
1828.52940.7804-0.6252
1838.57650.7501-0.6613
1848.62370.7181-0.6959
1858.67080.6845-0.7290
1868.71790.6494-0.7604
1878.76500.6129-0.7902
1888.81220.5750-0.8181
1898.85930.5358-0.8443
1908.90640.4955-0.8686
1918.95350.4540-0.8910
1929.00070.4115-0.9114
1939.04780.3681-0.9298
1949.09490.3239-0.9461
1959.14200.2790-0.9603
1969.18920.2334-0.9724
1979.23630.1874-0.9823
1989.28340.1409-0.9900
1999.33050.0941-0.9956
2009.37770.0471-0.9989
2019.42480.0000-1.0000
creating the dataframe
inc = locals().setdefault("inc", 2) + 1
df = pandas.concat([
    (x := Series(numpy.linspace(0, inc*numpy.pi, 201))).rename("x"), 
    x.apply(numpy.sin).rename("y"), x.apply(numpy.cos).rename("z")
], axis=1)
source code html
{% set format="%.4f" %}
<table role=table style="--x-min: {{df.x.min()}}; --y-min: {{df.y.min()}}; --z-min: {{df.z.min()}}; --x-max: {{df.x.max()}}; --y-max: {{df.y.max()}}; --z-max: {{df.z.max()}};">
    <caption>a sin wave</caption>
    <thead role=rowgroup class=visually-hidden>
         <tr>
         <th>index</th><th>x</th><th>y</th><th>z</th>
         </tr>
    </thead>
    <tbody role=rowgroup>{% for i, row in df.iterrows() %}
    <tr role=row style="--index: {{loop.index}}; --x: {{row.x}}; --y: {{row.y}}; --z: {{row.z}}">
        <th>{{loop.index}}</th><td>{{format % row.x}}</td><td>{{format % row.y}}</td><td>{{format % row.z}}</td>
    </tr>
    {%- endfor %}</tbody>
</table>

<figure>
<figcaption>creating the dataframe</figcaption>