Rendering images in Great Tables is straightforward with GT.fmt_image() and vals.fmt_image(). In this post, we’ll explore three key topics:
Four examples demonstrating how to render images within the body using GT.fmt_image().
How to render images anywhere using vals.fmt_image() and html().
How to manually render images anywhere using html().
Rendering Images in the Body
GT.fmt_image() is the go-to tool for rendering images within the body of a table. Below, we’ll present four examples corresponding to the cases outlined in the documentation:
Case 1: Local file paths.
Case 2: Full HTTP/HTTPS URLs.
Case 3: Image names with the path= argument.
Case 4: Image names using both the path= and file_pattern= arguments.
Finding the Right Case for Your Needs
Case 1 and Case 2 work best for data sourced directly from a database.
Case 3 is ideal for users dealing with image names relative to a base directory or URL (e.g., /path/to/images).
Case 4 is tailored for users working with patterned image names (e.g., metro_{}.svg).
Preparations
For this demonstration, we’ll use the first five rows of the built-in metro dataset, specifically the name and lines columns.
To ensure a smooth walkthrough, we’ll manipulate the data (a Python dictionary) directly. However, in real-world applications, such operations are more likely performed at the DataFrame level to leverage the benefits of vectorized operations.
Attentive readers may have noticed that the values for the key lines are lists of strings, each containing one or more numbers separated by commas. GT.fmt_image() is specifically designed to handle such cases, allowing users to render multiple images in a single row.
Case 1: Local File Paths
Case 1 demonstrates how to simulate a column containing strings representing local file paths. We’ll use images stored in the data/metro_images directory of Great Tables:
Local file paths can vary depending on the operating system, which makes it easy to accidentally construct invalid paths. A good practice to mitigate this is to use Python’s built-in pathlib module to construct paths first and then convert them to strings. In this example, img_local_paths is actually an instance of pathlib.Path.
from pathlib import Pathisinstance(img_local_paths, Path) # True
The case1 column is quite lengthy due to the inclusion of img_local_paths. In Case 3, we’ll share a useful trick to avoid repeating the directory name each time—stay tuned!
For now, let’s use GT.fmt_image() to render images by passing "case1" as the first argument:
Case 2 demonstrates how to simulate a column containing strings representing HTTP/HTTPS URLs. We’ll use the same images as in Case 1, but this time, retrieve them from the Great Tables GitHub repository:
Case 3 demonstrates how to use the path= argument to specify images relative to a base directory or URL. This approach eliminates much of the repetition in file names, offering a solution to the issues in Case 1 and Case 2.
Below is a Pandas DataFrame called metro_mini3, where the case3 column contains file names that we aim to render as images.
Show the Code
metro_mini3 = pd.DataFrame( {**data,"case3": [", ".join(f"metro_{item}.svg"for item in row.split(", ")) for row in data["lines"] ], })metro_mini3
name
lines
case3
0
Argentine
1
metro_1.svg
1
Bastille
1, 5, 8
metro_1.svg, metro_5.svg, metro_8.svg
2
Bérault
1
metro_1.svg
3
Champs-Élysées—Clemenceau
1, 13
metro_1.svg, metro_13.svg
4
Charles de Gaulle—Étoile
1, 2, 6
metro_1.svg, metro_2.svg, metro_6.svg
Now we can use GT.fmt_image() to render the images by passing "case3" as the first argument and specifying either img_local_paths or img_url_paths as the path= argument:
# equivalent to `Case 1`( GT(metro_mini3) .fmt_image("case3", path=img_local_paths) .cols_align(align="right", columns="case3"))# equivalent to `Case 2`( GT(metro_mini3) .fmt_image("case3", path=img_url_paths) .cols_align(align="right", columns="case3"))
name
lines
case3
Argentine
1
Bastille
1, 5, 8
Bérault
1
Champs-Élysées—Clemenceau
1, 13
Charles de Gaulle—Étoile
1, 2, 6
After exploring Case 1 and Case 2, you’ll likely appreciate the functionality of the path= argument. However, manually constructing file names can still be a bit tedious. If your file names follow a consistent pattern, the file_pattern= argument can simplify the process. Let’s see how this works in Case 4 below.
Case 4: Image Names Using Both the path= and file_pattern= Arguments
Case 4 demonstrates how to use path= and file_pattern= to specify images with names following a common pattern. For example, you could use file_pattern="metro_{}.svg" to reference images like metro_1.svg, metro_2.svg, and so on.
Below is a Pandas DataFrame called metro_mini4, where the case4 column contains a copy of data["lines"], which we aim to render as images.
First, define a string pattern to illustrate the file naming convention, using {} to indicate the variable portion:
file_pattern ="metro_{}.svg"
Next, pass "case4" as the first argument, along with img_local_paths or img_url_paths as the path= argument, and file_pattern as the file_pattern= argument. This allows GT.fmt_image() to render the images:
The file_pattern= argument is typically used in conjunction with the path= argument, but this is not a strict rule. If your local file paths or HTTP/HTTPS URLs follow a pattern, you can use file_pattern= alone without path=. This allows you to include the shared portion of the file paths or URLs directly in file_pattern, as shown below:
Case 4 is undoubtedly one of the most powerful features of Great Tables. While mastering it may take some practice, we hope this example helps you render images effortlessly and effectively.
Rendering Images Anywhere
While GT.fmt_image() is primarily designed for rendering images in the table body, what if you need to display images in other locations, such as the header? In such cases, you can turn to the versatile vals.fmt_image().
vals.fmt_image() is a hidden gem in Great Tables. Its usage is similar to GT.fmt_image(), but instead of working directly with DataFrame columns, it lets you pass a string or a list of strings as the first argument, returning a list of strings, each representing an image. You can then wrap these strings with html(), allowing Great Tables to render the images anywhere in the table.
Preparations
We will create a Pandas DataFrame named metro_mini using the data dictionary. This will be used for demonstration in the following examples:
Show the Code
metro_mini = pd.DataFrame(data)metro_mini
name
lines
0
Argentine
1
1
Bastille
1, 5, 8
2
Bérault
1
3
Champs-Élysées—Clemenceau
1, 13
4
Charles de Gaulle—Étoile
1, 2, 6
Single Image
This example shows how to render a valid URL as an image in the title of the table header:
Note that if you need to render images with different height or width, you might need to make two separate calls to vals.fmt_image().
name
lines
Argentine
Bastille
Bérault
Champs-Élysées—Clemenceau
Charles de Gaulle—Étoile
Manually Rendering Images Anywhere
Remember, you can always use html() to manually construct your desired output. For example, the previous table can be created without relying on vals.fmt_image() like this:
Alternatively, you can manually encode the image using Python’s built-in base64 module, specify the appropriate MIME type and HTML attributes, and then wrap it in html() to display the table.
Final Words
In this post, we focused on the most common use cases for rendering images in Great Tables, deliberately avoiding excessive DataFrame operations. Including such details could have overwhelmed the post with examples of string manipulations and the complexities of working with various DataFrame libraries.
We hope you found this guide helpful and enjoyed the structured approach. Until next time, happy table creation with Great Tables!
Appendix: Related PRs
If you’re interested in the recent enhancements we’ve made to image rendering, be sure to check out #444, #451 and #520 for all the details.