Nanoplots are tiny plots you can use in your table. They are simple by design, mainly because there isn’t a lot of space to work with. With that simplicity, however, you do get a set of very succinct data visualizations that adapt nicely to the amount of data you feed into them. Here’s some of the main features:
interactivity: you can hover over data and other elements to show values
choice of line and bar charting
you can annotate plots with a reference line and/or area
plenty of easy-to-use options for composing your plots
A simple line-based nanoplot
Let’s make some simple plots with a Polars DataFrame. Here we are using lists to define data values for each cell in the numbers column. The fmt_nanoplot() method understands that these are input values for a line plot (the default type of nanoplot).
This looks a lot like the familiar sparklines you might see in tables where space for plots is limited. The input values, strings of space-separated values, can be considered here as y values and they are evenly spaced along the imaginary x axis.
Hovering over (or touching) the values is something of a treat! You might notice that:
data values are automatically formatted for you in a compact fashion
the plot elements also display pertinent values
This sort of interactively is baked into the rendered SVG graphics that fmt_nanoplot() generates from your data and selection of options.
Polars lets us express ‘lists-of-values-per-cell’ in different ways and Great Tables is pretty good at understanding different column dtypes. So, you can alternatively create the same table as above with the following code.
Both forms of the numbers column in the two DataFrames look the same to fmt_nanoplot(). The key for the list of values (here, "val") can be anything as long as it’s repeated down the column. So the choice is yours on how you want to prepare those column values.
The reference line and the reference area
You can insert two additional things which may be useful: a reference line and a reference area. You can define them either through literal values or via keywords (these are: "mean", "median", "min", "max", "q1", "q3", "first", or "last"). Here’s a reference line that corresponds to the mean data value of each nanoplot:
As an added touch, you don’t need to worry about the order of the keywords provided to reference_area= (which could be potentially problematic if providing a literal value and a keyword).
Using autoscale= to have a common y-axis scale across plots
There are lots of options. Like, if you want to ensure that the scale is shared across all of the nanoplots (so you can better get a sense of overall magnitude), you can set autoscale= to True:
If you hover along or touch the left side of any of the plots above, you’ll see that each y scale runs from -12.0 to 37.0. Using autoscale=True is very useful if you want to compare the magnitudes of values across rows in addition to their trends. It won’t, however, make much sense if the overall magnitudes of values vary wildly across rows (e.g., comparing changing currency values or stock prices over time).
There are many options for customization. You can radically change the look of a collection of nanoplots with the nanoplot_options() helper function. With that function, you invoke it in the options= argument of fmt_nanoplot(). You can modify the sizes and colors of different elements, decide which elements are even present, and much more! Here’s an example where a line-based nanoplot retains all of its elements, but the overall appearance is greatly altered.
As can be seen, you have a lot of fine-grained control over the look of a nanoplot.
Making nanoplots with bars using plot_type="bar"
We don’t just support line plots in fmt_nanoplot(), we also have the option to show bar plots. The only thing you need to change is the value of plot_type= argument to "bar":
An important difference between line plots and bar plots is that the bars project from a zero line. Notice that some negative values in the bar-based nanoplot appear red and radiate downward from the gray zero line.
Using plot_type="bar" still allows us to supply a reference line and a reference area with reference_line= and reference_area=. The autoscale= option works here as well. We also have a set of options just for bar plots available inside nanoplot_options(). Here’s an example where we use all of the aforementioned customization possibilities:
Single-value bar plots, running in the horizontal direction, can be made by simply invoking fmt_nanoplot() on a column of numeric values. These plots are meant for comparison across rows so the method automatically scales the horizontal bars to facilitate this type of display. Here’s a simple example that uses plot_type="bar" on the numbers column that contains a single numeric value in every cell.
single_vals_df = pl.DataFrame( {"example": ["Row "+str(x) for x inrange(1, 5)],"numbers": [2.75, 0, -3.2, 8] })GT(single_vals_df).fmt_nanoplot(columns="numbers", plot_type="bar")
example
numbers
Row 1
Row 2
Row 3
Row 4
This, interestingly enough, works with the "line" type of nanoplot. The result is akin to a lollipop plot:
You get to customize the line and the data point marker with the latter display of single values, and that’s a plus. Nonetheless, it is more common to see horizontal bar plots in tables and the extra customization of negative values makes that form of presentation more advantageous.
Line plots with paired x and y values
Aside from a single stream of y values, we can plot pairs of x and y values. This works only for the "line" type of plot. We can set up a column of Polars struct values in a DataFrame to have this input data prepared for fmt_nanoplot(). Notice that the dictionary values in the enclosed list must have the "x" and "y" keys. Further to this, the list lengths for each of "x" and "y" must match (i.e., to make valid pairs of x and y).
The options for removing the data area and the data line (though the corresponding show_* arguments of nanoplot_options()) make the finalized nanoplots look somewhat like scatter plots.