Resources

Great Tables 1: Structure, Format, and Style

This workshop is all about using Great Tables to make beautiful tables for publication and display purposes. We believe that effective tables have these things in common: structuring that aids in the reading of the table well-formatted values, fitting expectations for the field of study styling that reduces time to insight and improves aesthetics These materials are for you if: • you have some experience with data analysis in Python • you often create reporting that involves summarizations of data • you were often frustrated with making tables for display purposes outside of Python • you found beautiful-looking tables in the wild and wondered: 'How could I do that?' Other videos in this series: Great Tables 2: Introducing Units Notation: https://youtu.be/SN0_vIL1Rhk Great Tables 3: Data Color and Polishing https://youtu.be/Huteb5OmcrA About us: Michael Chow, Senior Software Engineer, Posit Michael is a data scientist and software engineer. He has programmed in Python for well over a decade, and he obtained a PhD in cognitive psychology from Princeton University. His interests include statistical methods, skill acquisition, and human memory. Richard Iannone, Senior Software Engineer, Posit Richard is a software engineer and table enthusiast. He's been vigorously working on making display tables easier to create/display in Python. And generally Rich enjoys creating open source packages so that people can great things in their own work. Workshop repo: https://github.com/rich-iannone/great-tables-mini-workshop?tab=readme-ov-file Learn more at https://posit-dev.github.io/great-tables/articles/intro.html

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Hey everybody, my name is Michael Chow, and I'm joined with Rich Iannin as we do this little tiny workshop on Great Tables. So just a little bit about us, we're software engineers at PositPBC. Collectively we have two PhDs, two dogs, and five cats, and we're total fanatics about table display.

So in this workshop, the way it's set up is we'll alternate between slides and a code along. So in the slides, we'll give you a basic understanding of simple Great Tables concepts and functions. In the code along, we'll code through some different tables so you can see how they're made and get some practice in making tables. And the workshop materials are online, so you can find them on GitHub, on Rich Iannin, Great Tables mini-workshop. And if you have any questions, we have a Great Tables Discord, so we'd love to have you join, and it's super helpful when people ask questions about Great Tables.

What is a display table?

So the big question with display tables is, what is a display table? So essentially, Great Tables is a Python library for creating publication-ready tables. And what we mean by that is less like the table on the left, which is a raw Polars data frame, and more like the table on the right, which is a formatted, styled, beautified table that you might put in a report. And the big reason is the table on the left is really useful if you're doing data analysis. You really want to know the names of your columns. You want to see all of your data. But the table on the right's really useful when you want to hand it off to someone and to publish insights and try to spur people to action. So Great Tables is all about the table on the right.

So I'm going to go through some really nice display tables that we found on the internet to just try to highlight some of the value of publishing tables and formatting them nicely for presentation. So here's one about a basketball team. So history does not bode well for the Hoosiers. This is about a specific team. The thing I want to emphasize here is a few pieces. We have a heading, which lets you put a title and some high-level information. We have a spanner, which groups columns together with a high-level label. We have these team logos for conveying each team really quickly. And then we can also highlight rows. So this row is the topic of this article we found it from, and it's highlighted to draw attention to the main subject. And then we also have these percentage values here. So notice percentages here are formatted nicely to just be two decimals for people.

So this is a really good-looking table, and it's a nice way to communicate information clearly. It's got a little bit of emphasis. It's got some labels and a lot of nice pieces for presentation.

Here's another one. So this is about a specific basketball player. So this table, some nice things about it are it has bar charts. So you can actually include small graphics in your table. It also has the rows split up. So there's some grouping behind the rows. And then the last thing is it has these footnotes here for providing additional details.

And the last table to show you is this table that's CO2 intensity and power consumption by country. So notice this has countries ordered by their CO2 intensity, and then it has them the percentage of different power sources that they consume. And notice the use of color here, that this table is able to code more green sources of power against dirtier sources of power here. And we're able to see through this heat map trends that countries that tend to have low CO2 intensity tend to use cleaner sources. So this is a really neat way that tables can provide sort of heat map information to people.

So this is a really neat way that tables can provide sort of heat map information to people.

We have nicely formatted percentage values and then a heat map here to make it easier to pull out patterns.

How Great Tables came to be

So these three tables are made from code. And that's part of the powers that you can basically maintain a reproducible workflow in Python, where you take data from input to reporting all with Python code. A big question is how did we get here? So this was mostly the work of Rich Ianan in figuring out how to generate the right API for creating display tables. As it turns out, there are a lot of books on data analysis and plotting, but it's a lot harder to find books on table design.

One book in particular stood out, and this is the Census Manual of Tabular Presentation. It's a pretty old book, but it contains basically tons of concepts on how to display tables and a lot of really useful recommendations on creating tables. So this was published way back in 1949. But as it turns out, it's super relevant even today. So here's an example about how to formalize the structure of a table and different parts of a table and even names you might give to them. And that's exactly what we used today.

So here we have this modern take on the table display framework that powers Great Tables. So notice we have parts like a header with a title and subtitle. We have column labels with something called a spanner label, which is high-level columns. And then we have everything in the table body and source notes. So a lot of different pieces of the table put together here. And the hope of this graphic is just to provide an easy way to get a sense for the pieces of a table.

So a big question is, how do you make tables today? So if you have this raw table, the big question is, what do you do to take it from this raw input to display? You could show this table to people, but it's not the cleanest to read or to pull things out of. A really common workflow we see is Excel. You could instead copy your data out into Excel to make a nice-looking table. But the big challenge here is now that you have a broken workflow, and it can be hard to reproduce. There could be quirks in Excel that could be hard to capture. And so essentially, your workflow has broken. With Great Tables, you can do everything entirely in Python. So you can have a nice, reproducible Python workflow from beginning to end.

Structure, format, and style

So to recap, Great Tables is a package focused purely on displaying tables. It's not the only approach you can use out there in Python, but we've tried to make it comprehensive. We develop it actively. And we've tried to really capture a really wide range of table problems out there.

So this workshop is to help you learn the process and design behind making presentation-quality tables. So in this first part, I'm going to talk a bit about structure, formatting, and styling. So to go through, we're going to use this example table that we'll call the coffee table. And we're going to walk through its different pieces. So this table is mostly made of three pieces, structure, format, and style. And the structure pieces are pieces like the title, these column spanners, which go over our column labels, and then cleaning up the column labels themselves. For format, we have things like formatting currency values, for example, to put a dollar sign and commas in the right place, and percentages. So notice the percentages here are whole values. So we just clean them up a little bit for presentation.

And the last piece is styling. So notice that we've filled the color for some of these rows. So all the revenue columns are Alice Blue, and all the profit columns are Papaya Whip. The other thing we did is we bolded the text on the bottom row so that it's a little bit easier to see that it's totaling everything, and it's a little bit different from the other rows of the table. So that's the basics of structuring, formatting, and styling.

Setup and Polars selectors

So let's talk a little bit about setup, because there are a couple pieces before we go into the code used to create tables like that. There's a couple pieces to get out of the way. So the first is Great Tables works really well with Polars. And if you've never used Polars, Polars is a data frame library for Python that's really taking off and has a lot of really nice, a really good API design that makes it easy to work with. Great Tables also works with Pandas, but we'll use Polars for all our examples in our code. And one thing you need to know is that Polars has a neat concept called selectors. These make it easy to select columns of data using a really convenient syntax. So here we import Polar selectors, and we can say something like starts with revenue, and that will select all the revenue columns of our data. This will be really useful because we'll use this a lot in Great Tables to, for example, put labels over columns or to grab columns to format in our table.

Structuring tables

So with that out of the way, I'm going to go into the basics of structuring tables. So what we're going to do is we're going to use this example table from Great Tables called Exible to show off all the pieces that I walked through before, the structuring, formatting and styling. So to get this table, we import Exible from Great Tables and this class GT, which is the class that powers all of the Great Tables fun.

So this is when we call GT over Exible, we just get this really basic table with really simple formatting to start out. So let's go through first making row labels. So we have these row names in this column called row. And what we can do is we can use the simple argument row name call to sort of set the row on its own. So this is called the stub. And this sort of just creates a divide between the rows and the table. This is useful for adding a little bit of emphasis to row names.

So that's a really simple activity. Another one is that we can make row groups. So we have this group column right here. And we can do that simply by adding another argument group name call with the column name for our groups. And then notice that that will create these sort of horizontal rows that mark each group. So now our groups are sort of marked from each other. And this makes it really easy to sort of group rows and split them up. So it's easy to see which rows belong together.

So just to compare the table we started with and the one with a stub and row groups, notice the basic GT table is on the left and the sort of gussied up one we made is on the right with row groups and a stub. So the next thing you might want to do is add a title to your table. So to add a title, what we'll do is we'll just use this really simple tab header method with the title argument. So notice we've added the title table title right here. So pretty easy. You can also add subtitles by adding the subtitle argument to tab header. So pretty quick, but lets you explain your data a little bit more.

So next up, we're going to add spanners, which are rows above our column labels. So to do this, we'll use the tab spanner method. So our key here is we'll pass it two arguments. So we're going to pass it the columns argument, which is the columns we want to put a label above, and then a label argument, which is the label itself. So notice we put the label of spanner above date time and date time. And there it is in the data, just right above our column labels. The next method is calls label. So what calls label does is it renames our columns. And this is really nice because in the data, column names often have underscores, they're often all lowercase. So this is a chance to clean up the names.

Formatting values

So in the last section on structure, we looked at creating a stub with row names, creating groupings of rows, and then adding a simple title with tab header, column labels with calls label. And then we use tab spanner to add high level labels over our columns. In this next section, we're going to go through the basics of formatting. So how to clean up the values of the data themselves. And the thing to know is there's a ton of formatting methods in Great Tables. So we've really bent over backwards to try to accommodate tons of situations. And if you think about it, when people copy their data into Excel, they're using tons of formatters in Excel to format dates and percentages and things like that. So we've tried to really bring that like essence of Excel formatting into Great Tables.

So they all start with FMT for format. And there's quite a few around like numbers, integers, currencies, and then a lot of date related ones as well. So there's a huge variety of methods available.

So we're going to go through two of them. The first one's format currency. So this is to format monetary values. So we'll start with this example table again, just to have a base to work from. And then what we're going to do is we're going to format this currency column here. So notice that it doesn't have dollar signs, and it has three decimals in a lot of places, which might not be what we want to represent. So to do that, we're just going to use the format currency method and pass it the currency column. And what it's going to do is it's going to put a dollar sign in front of currency and just use the two decimal places. Since by default it formats for USD, US currency, but you can also set it to other ones. And just to show you, this is the before and after. So notice the dollar sign and fewer decimals here.

So the next formatter I'm going to look at is format percent. And this is to format data as percentages. So right now we have this value column. Sorry, we're going to create this data to show off format percentage since it's a little hard to show off in Exible, but these kinds of problems show up a lot. So in this new data we're creating, notice we have these values here that we might want to format as percentages. So what we do is we just call the format percent method on this value column. And what we get back is the percentage sign after, and notice the decimals are shifted. It basically takes the first two decimal places as percentages. So just to show you a little bit closer, notice 0.02 is rendered as 2% here. So pretty simple, but makes a big difference when you're doing a lot of reporting.

Styling with tab_style

So with structure and formatting out of the way, we're going to go through styling the table with a method called tab style. So tab style is a little bit more complicated than the other things we looked at, but it's not too much more difficult. It just involves a couple pieces for customizing what we want to style and how. So the key is tab style takes two arguments, style and locations. And so we use helper functions from Great Tables to specify these two pieces. And the key is that style is like the what, and locations is like the where. So what kind of styling are we going to use? Are we going to color the text? Are we going to fill the background? And location is where should we do that in the data?

So here's a few examples. So for styling, you can either fill the background. You can change the text, or you can modify borders. And for location, the most common one is loc body, which says somewhere in the body of the table we're going to change something, but we have others for targeting all the parts of the table now that you can apply styles to. So for these examples, we're going to import the style and loc sub modules, and those contain the pieces we need for using tab style.

So to go back to this simple table example, we're going to use the tab style method. And what we're doing here is we're going to fill the number column to be light blue. And the way we do that is we use style.fill with color equals light blue as the what. So we pass that to style. And then for locations, we use loc.body. And then notice that loc.body lets us specify the exact column to apply the style to. So in loc.body, we specify num to say we're coloring the number column or the num column. So that's the gist of tab style. And tab style is really neat. It can do a ton of stuff with text. It can do a ton of stuff with locating different parts of the tables. And we find that this is one of the pieces that people ask about most because it lets you customize the table and really do a lot of emphasizing and fitting for your use case.

Nanoplots, images, and missing values

So we went through structuring, formatting, and styling. There's just three last things that aren't so much Great Tables concepts as things we think are super exciting that we just wanted to emphasize. So these things are nanoplots, images, and dealing with missing values. After we apply these things, we get this neat version of the table. So for nanoplots, we can add tiny bar charts to a column. For format image, we can add icons really easily or tiny images. And for submissing, it's really nice for hiding missing values. So here, we had a none that I think showed up as na. With submissing, you're able to hide values like that. Notice these are formatters, but we also find that they're so exciting, we just wanted to highlight them here.

So we went through the basics of structuring, formatting, and styling. We showed you some of the things we think are neatest, like nanoplots and images. Now's a chance to try it out. So we're going to code along to create the coffee table that we walked through so you can see it built end-to-end and get a feel for Great Tables in action. All right. Thanks for watching, and we'll go to the code along.

Code along: the coffee table

So basically, the repo for the coffee sales data, it comes from right here, github.com, mhl slash coffee hyphen sales hyphen data. That's where the data actually originates from. And the great thing is we have an example notebook. We have another README right here, some really useful pieces for this. But importantly, this shows what the table looks like right here, which is a table that has two sets of columns, amount percent for revenue and profit. It has some visualization of the monthly sales for the sales of coffee equipment. It shows the products, both in terms of icon form and also in name. And the bottom shows a total row. So it shows the total sales of all types of equipment throughout the year.

And just one note, too, if I understand it's sales data for like a fictitious coffee shop over the course of a year. Exactly. Not a real coffee shop at all. We don't have that kind of data. Not yet. No. Yeah. One day. We're talking to those coffee shop owners, but they won't budge. They won't give us the data.

And I suppose this will be linked in the notes for the video as well. But yeah, essentially, this is all the materials. If you clone this, you'll have everything. Code along was right here, py01, sorry, 01 coffee table, qmd. qmd is our quarto documents. You may or may not quarto, and that's totally cool. If you do not like that, we have ipymb files here as well. And I believe GitHub has a nice renderer for ipymb files, so here they are as well.

You're seeing my code inside of VS Code. I have it right here. I'm just going to code along. A lot of stuff is blank, so I'm going to type stuff in as we move along. So the first thing we got to do, and this is a quarto document, just so you know. I'm going to run quarto cells here, and we're going to see the results in this display over here on the side. So the first thing we have to do is, of course, import. We're going to import polars, and then also the polar selectors, and also Great Tables. From that, we're going to import gt. That's like the entry point for the API. And then look and style. We're going to use that a little bit later, but that's going to be for styling the table.

So the first thing we're going to do is import a JSON file. We have, as part of the exercise files here, we're going to use something from polars, data frame deserialize. It's a little bit eccentric, but it just sort of makes it a little bit easier to get the data in in the right form initially. So I'm going to run that right now. And we see right here on the side, we have a table. It's nothing like a display table you want to show other people, but it is a table, and it has all the information we need to make a great table.

So let's get this data, coffee sales data, into Great Tables. So what we're going to do for the rest of this code along is we're going to assign it to separate objects, and then sort of build, you know, as we go with these separate objects and see the result. So we're going to use coffee sales, which is our variable, which has a table, introduce that to GT class. We're going to run that cell. And here we are. I'm just going to scroll back so we can see the headings of this table, this very large table. This is an HTML table. It's going to look much nicer once we basically use the different methods inside of Great Tables.

So the first thing we want to do is some structural stuff. We want to add a title to the table and explain what's in this table. So I'm going to uncomment these little bits right here. And the method we need for this is tab header. Great. We sort of see some autocomplete stuff. We see what we need. It looks like here we need title and or subtitle. In this case, we're just going to use title. And the title I want in this one is just going to be coffee equipment sales for 2023. Sort of like fake sales, really. I'm going to run this cell with my shortcut here. Great. It updated the table, but we can't see it until I scroll to the top. I'm just going to verify that the title is entered, and it is right here. Coffee equipment sales for 2023.

So the next thing we want to do, because this is a great start now, we want to do things like add more structures to the table. So my next little instruction here, my little brief, is to group numerical columns with a spanner. One grouping should be for revenue columns. So revenue dollars, revenue percent. Another should be for profit columns. So these two columns right here on the side. So I'm going to do that in a similar way. Uncomment this code here, this commented code. And for this, I'm going to use two invocations of tab spanner. So tab spanner, it takes in two important arguments. The label and some sort of column selection. So the first thing I'm going to do is use tab spanner, and the label, I'm going to start with the revenue columns. So I'm going to call this label revenue. And next part is columns. It needs to know which columns to group under the spanner. In this case, I'm going to use CS, which is actually column selectors from pollers. We just import that as CS. So it's going to be CS starts with, I'm going to autocomplete that. And in this case, it's going to be revenue, lowercase. So I'll get the first, the columns that begin with revenue.

Goes to the next line, second instance of tab spanner. The label in this case will be profit of capital P. And the columns in this case will be starting with profit. So columns will equal CS starts with profit. So now I'm going to run this. Great. So this updated. We're at the bottom of the table, so we have to scroll up to see the effect. But the effect is that we have revenue above the revenue columns and the spanner label profit above the profit dealing columns.

And Rich, do you mind saying a little bit about why you would use tab spanner like that? Yeah. It's great for grouping. So people can just see right away, oh yeah, this part of the table just deals with revenue. So whatever columns deals with that. This part is focused on profit. We can just get a quick sort of like, we don't have to like parse like the names of like the columns and also avoid some redundancy. We can imagine later on we can have revenue and we can have it, we don't have to repeat revenue here. We can just say dollar amount or percentage. Right. Yeah. So it's kind of like a mapping, which is kind of convenient. And we see it in tables all the time. So it's actually quite natural. And you know, like people know how to parse that.

So we got these, these are great. These spanner labels. The problem is our column labels, they don't look too incredibly great now. They're super redundant also. So we're going to fix those with a different method. We're going to take gdTable3 and this case, we're going to use callsLabel. That allows you to relabel the columns, the column labels. Right now they're just taken from like the column names in the original dataset. That's usually never what you want. You usually want to relabel them. So in this case, we have to do things like use revenue dollars. We have to give the column names and then the label that we want. So amount in this case. So we'll do the same thing, revenue percent, like that. And just use percent here. I'm going to copy these both because we're going to do the same thing for the profit columns.

So if I run this cell, scroll to the top, takes a while, we'll get there. There we go. And now we have like amount, percent, amount, percent, monthly sales. Okay. Still not looking great because we're not really finished yet. We have to deal with a few more things. And a lot of it has to do with formatting.

So we'll move on and we'll do a thing now where we change these values, which are not really friendly for amounts, into currency values because we're talking about coffee equipment sales for 2023. So in this case, and I'm also going to rerun this as well to put that back because we'll need that later, that column again. So in this case, we'll want to use a method called format currency. And in this case, we do want to target all the amounts or all the columns that have dollars in the name. We can't see here, but we know that it ends with dollars. So in this case, we'll use columns because that's what it needs initially. And we'll use, yes, ends with, in this case, dollars. And also we'll do another thing with this. There's lots of options inside each of these methods for formatting, but in this case, we don't need the cents amount. Like it'll by default include cents along with dollars. So we'll use an option called use subunits. It's initially true, like by default, but we'll set it to false.

So in this case, we'll want to use a method called format percent. And again, we can target columns. Just to be sure, like, because we can't see the column names here, like how would you check them to know the column? It's going to be a bit of a scroll back. Yeah. So we can definitely go to calls label or we can entirely omit this calls label till the very end. Yeah. Is that something you do often? Like leave calls label to the end or how do you usually? I usually do that. Yeah. Yeah. It's a good strategy, but you wouldn't know that until you do it the wrong way first. Like I did, which is not necessarily the wrong way, but it gets, it gets a bit unwieldy when you have lots and lots of columns.

So this is definitely another case of using ends with, because they're named in a systematic way. We do ends with PCT. I think in this case, we don't, we want to have no decimal places showing just like the dollars, um, deal. So we'll use decimals by default is two, but in this case I want zero. So I'll run that. And again, you can choose whether you want fractional percentages, but I think in this case you won't even see anything there. So this is quite nice.

Applying styles to the coffee table

And now we're going to do some styling. This table looks good, but it could look even better with a little bit of styling applied. So in this case, um, what we have here as a design brief is to use an Alice blue background for the columns that pertain to revenue. So obviously these two columns here under this pattern. So we can totally do that. We can use tab style for that operation, so tab style. And this method has two different arguments, style and locations. So make a note of this because at the beginning we had to import, I'm going to scroll back, look and style. This is, these two classes are specifically needed for tab style. If you don't have this imported, you won't be able to use tab style. So the key thing is to import those if you're using styles and then to use them in the two different arguments.

So in this case, what we'll do is we'll start with style and that'll be equal to, so this is the thing we imported style, particular thing inside of style we want to use is fill in this case. So it pops up at the top. There's borders, fill and text in this case we want fill because we want to change the fill color of these cells. And these have different arguments. The only argument here is actually color and we're going to use the color Alice blue. So it recognizes things like color names, like CSS color names, and it can all be written in lowercase like this. Second argument is locations. In this case you need to use the loc class and within that you'll see there's one thing body here. So within that, there is two arguments, columns and rows. In this case, we want to fill the entire column, um, you know, of, of revenue, like wealth revenue columns, uh, with that style. So in this case it would be columns. And here again, we can use CS starts with, and we're going to target columns that start with revenue. So I'm going to run this and we do see that we got the result we wanted. We got Alice blue filling the body cells of the revenue columns with the Alice blue color.

So now we're going to do the exact same thing or pretty close, pretty much the same thing with a different color for profit. And so what I'll do there is I'll come at this and I'm just going to copy this for sake of expediency and just change a few things. In this case, we're still using style fill because we're just filling columns with a color. In this case, it's papaya whip. And this time it's not things that start with revenue. It's going to be things that start with profit.

So I'm going to run that right here. Oh, it did not seem to take. Let's take a look here. Papaya whip. Look, body. Is papaya misspelled? Is that? I think it is. Yeah. There we are. Okay. You did it. I love the teamwork. Teamwork. Oh, my God. That's what does it. There we are. Now we got it. So rule of thumb is always know how to spell papaya whip or any color that you want to use. There we are. It looks great so far.

So here's another thing. We have a row, which is pretty much like a summary row. We have a total and total dollar and percentage amounts. What we want to do is make that prominent by making the text bold in the bottom row. Let's do that. It's going to be a case, again, of using tab style, but it's going to be a little bit tricky because we have to use an expression. If you know polars really well, maybe this won't be difficult, but it might be something that trips you up. So let's go through it slowly. So the first thing is style. We're going to fill in that argument with the style we need. In this case, it's not style fill. It's going to be style text. And there's many options in here. I'm going to shortcut it by just saying the option we want is weight. In this case, the weight value will be bold. That's taken care of. And now how to target the entire bottom row. A little bit tricky. So let's start with the argument name locations. Just so you know, that's is it. Look body. In this case, we want to use the rows argument. And we want to use pl call product. So in the product column, we want to target the row that has total in it. So what this returns, this expression, is the row number. That's going to be applied to all columns, because by default, all columns are chosen. So here we go. I'm going to run this. Great. So that worked. So the tricky part here is remembering pl call and putting the column that's focused on inside that. And then, like, making that equivalent to total.

Adding nanoplots and images

So a few more things we want to do is add a column of bar plots to the monthly revenue column. We axed that earlier on. But we can get it back. We just have to remove and rerun some stuff. So I'm going to do it right now, because we've shown that this works, and it's a little easier to see. Let's remove that calls hide statement, which is right here. It's served its purpose. And now let's go down to the part that we want to modify. Let's run all the stuff above first.

So the thing we're going to focus on is this list column right here. Basically, this contains data for plots right here. We call them nanoplots. Monthly sales. So how do you get that in the table? I know it might be, if you ever heard about list columns, they're kind of a funny piece of data. Do you want to say a little bit about what a list column is? Because it's kind of a funky. Yeah. As far as I understand them, they just contain lists within each cell of the column. And I believe that they contain lists all the way down. Otherwise they're not valid. I'm not sure what the rules are for, like, you know, I think they contain various size lists. I believe that's how it works. But the key thing is that there's lists in each cell within a column. Yeah. Yeah, I think so. It's like where normally you just have a single number. You can have a list or array of numbers. And it can be any, like, length.

So I'm just going to use the method called format nanoplot. And the first thing we need is columns. So we're going to focus on that column, which is monthly sales, because that is the list column, which contains the data. And in this case, like, the default is, like, a line plot where it just shows a line connected with basically a bunch of data points connected by a line. We don't really want that in this case. We want the different plot type, which is a bar plot. So that's one of the keywords here. Plot type bar. We're going to hope for the best. Run that. I do have to scroll up because, like, space is limited here. I'm trying to make this pretty large for the purpose of the video, but it necessitates a little bit of scrolling. We can see here if we hover over the different bars of the nanoplot, we see the actual values, which is really, really cool right there. And it does its best to sort of make these values kind of small. We see here things like 521, 496. But for large values, we have values like 4.74K. So it tries its best to condense the values so they actually fit in this small plot space because it's limited space.

We can see here if we hover over the different bars of the nanoplot, we see the actual values, which is really, really cool right there.

So it really is super cool, I would say. Incredible. Thank you. Nanoplots just blow my mind every time. And they're fun. You can just hover over it. It's like, oh, my God. Like, this is ‑‑ it's got a lot of dense information here. It's got, like, the trends that it's showing. It's also showing the values, should you need them. Two for one deal.

Yeah, might be worth noting, like, anything interesting in there, like, what you might find in the nanoplots. Yeah, yeah. I'm seeing right away that, like, some things are peaking in the summer. Some things more than others. Like, cold brew. It's very obviously a summer thing. In the winter, nobody's caring about cold brew. Right. Like, you know, I guess these coffee sales occur somewhere, you know, with four seasons, maybe. But, yeah, we're sort of seeing that right there. And we're also seeing, what else do we see? Espresso machine. It's very much a few months at a time. Just like Christmas, it does pretty well.

And you may have noticed a long time ago, like, when we started this, we had these, like, this column called icon with very obviously file names for images. We're using that now. So we can add images to the icon column. The input for an image is the file name itself. And we can use a method called format image. And the thing you've got to do there is just point towards where the images really live on disk. And like many of these formatters, the first argument is columns because we want to tell Great Tables what column to focus on. So in this case, it would be icon. That's part one of the puzzle. The second piece is essentially the path to the images. Do you mind showing people where the images are? Like, how do you know where the images are? Yeah, this requires a bit of preplanning from the user. We have in our exercise files an image directory just in the root of the project. And here they all are. So they're within image. And these names do match these names. If they don't, you'll find out pretty quickly. So this, again, involves a little bit of preplanning, some being systematic with your file names. But once you do this, once you have them lined up in terms of file name and the actual name used in the table, you do get the images.

So right now, CoffTable, it is in Codelong right here. It's in a subdirectory inside the root. Like, it's in a subdirectory. So we have this right here. So we do have to go back into the root and then go to image, right? So in this interactive way I'm using my Great Tables demonstration, I have to do this and then provide the directory image right here. Because what happens is this sort of, like, combines with this to give you paths, relative paths.