Skip to content

Tables

Pyreball allows printing pandas DataFrame objects into HTML tables with print_table() function. Moreover, Pyreball uses DataTables library to add styling and interactivity to the tables.

Basic Usage

The simplest usage is to provide just a DataFrame object:

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    }
)
pb.print_table(df)

Captions

All tables are numbered by default, which causes creation of Table 1. caption above. It is possible to provide custom caption text via caption parameter. To control whether Table k. prefix should be displayed, numbered Boolean parameter can be set accordingly.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    }
)
pb.print_table(df, caption="People with their age.")
pb.print_table(df, caption="People with their age.", numbered=False)
pb.print_table(df, numbered=False)
pb.print_table(df, caption="The table with numbering again.")

Note

All tables are internally numbered, even though the numbering might be turned off for specific tables, as shown in the previous example.

Caption Position

By default, the caption is positioned above the table. The position can be controlled by caption_position parameter, which can be set either to top or bottom.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    }
)
pb.print_table(df, caption="Top caption.", caption_position="top")
pb.print_table(df, caption="Bottom caption.", caption_position="bottom")

Aligning Tables

Tables can be horizontally aligned by align parameter, as shown in the following example.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    }
)
pb.print_table(df, caption="Left align.", align="left")
pb.print_table(df, caption="Center align.", align="center")
pb.print_table(df, caption="Right align.", align="right")

Aligning Columns

Numeric columns are aligned to right and columns of other types to left, by default. This behaviour can be changed through col_align parameter. The parameter takes either a string (to set the same alignment for all columns), or a list of strings (to set the alignment of each column individually). When a list is provided and index is displayed, the list must contain also values for the index columns.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    },
    index=[1, 10, 100, 1000],
)
pb.print_table(df, caption="Default alignment.")
pb.print_table(df, caption="Identical alignment.", col_align="left")
pb.print_table(
    df,
    caption="Heterogeneous alignment.",
    col_align=["center", "right", "left"],
)

Sorting

It is possible to make the table sortable on all columns by setting sortable parameter to True, or by setting sorting_definition parameter, which also sorts the table initially on the specified column(s).

Parameter sorting_definition expects a list of tuples, where each tuple contains a column index and string asc or desc. The table is primarily sorted according to the first tuple, secondarily according to the second tuple, and so on.

The following snippet shows the usage of both parameters.

Note

Although the columns in sorting_definition are indexed from 0, it is necessary to take into account also the table index when it is displayed. To hide the index, set index parameter of print_table() method to False. index parameter is one of the kwargs parameters that are passed to Pandas to_html() method, which is used internally by Pyreball.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave", "Alice"],
        "age": [23, 5, 2, 54, 18],
    }
)
pb.print_table(df, caption="Sortable table", sortable=True)
pb.print_table(
    df,
    caption="Table sorted by age (ASC).",
    sorting_definition=[(df.columns.get_loc("age") + 1, "asc")],
)
pb.print_table(
    df,
    caption="Table sorted by name (ASC) and age (DESC).",
    sorting_definition=[(1, "asc"), (2, "desc")],
)
pb.print_table(
    df,
    caption="The same table, but without the index.",
    index=False,
    sorting_definition=[(0, "asc"), (1, "desc")],
)

Dealing with Large Tables

Each table is fully displayed by default. This is caused by keeping the display_option parameter to its default value full. However, this might not be practical for large tables.

One solution is to allow vertical scrolling of the table by setting display_option to scrolling. To change the default height of the table, set also scroll_y_height parameter.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    [[row * 20 + col for col in range(20)] for row in range(40)],
    columns=[f"col_{i}" for i in range(20)],
)
pb.print_table(
    df,
    caption="Larger table with scrolling.",
    display_option="scrolling",
    scroll_y_height="500px",
)

Note

By default, Pyreball turns on horizontall scrolling on each table as can be seen in the previous example. You can turn it off by setting scroll_x parameter to False. This, however, might cause the table to overflow the container.

Another option is to set display_option to paging. This option can be further customized by providing custom page sizes through paging_sizes parameter. Currently, paging_sizes takes a list of integers mixed with string All (the case of the letters does not matter, so it can be all or ALL as well). When All is used, Pyreball interprets it as showing all entries on a single page.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    [[row * 20 + col for col in range(20)] for row in range(40)],
    columns=[f"col_{i}" for i in range(20)],
)
pb.print_table(
    df,
    caption="Larger table with paging.",
    display_option="paging",
    paging_sizes=[5, 10, "All"],
)

Searching

To allow searching within a table, just set search_box to True.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    }
)
pb.print_table(
    df,
    caption="Table with a search box.",
    search_box=True,
)

Complex Headers and Indices

Pandas allows its users to create complex (multi-level) headers and indices. Such tables can be also printed into HTML, which creates additional columns and header rows, as can be seen in the following example. The code snippet also shows how to display index columns as regular columns.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    [
        ("Bob", 2, 12, 23, 49),
        ("Carol", 54, 42, 2, 4),
        ("Alice", 20, 4, 18, 19),
        ("Dave", 42, 21, 43, 23),
        ("Eve", 7, 12, 55, 6),
        ("Frank", 1, 5, 48, 38),
    ],
    columns=pd.MultiIndex.from_tuples(
        [
            ("name", ""),
            ("current", "x"),
            ("current", "y"),
            ("previous", "x"),
            ("previous", "y"),
        ],
    ),
    index=pd.MultiIndex.from_tuples(
        [
            ("red", "dev"),
            ("red", "dev"),
            ("red", "qa"),
            ("blue", "dev"),
            ("blue", "dev"),
            ("blue", "qa"),
        ],
        names=["team", "role"],
    ),
)

pb.print_table(
    df,
    caption="With index.",
    sorting_definition=[(2, "asc")],
)
pb.print_table(
    df.reset_index(),
    caption="Without index.",
    index=False,
    sorting_definition=[(2, "asc")],
)

The example also shows that when defining sorting on columns via sorting_definition parameter, a user must take into account index columns too. Index columns must be also taken into account when setting col_align parameter.

Note

Pyreball sets sparsify parameter of Pandas to_html() method to False, because DataTables would not be able to display tables with a multi-index correctly, especially not with sortable columns. This is also the reason why the identical team values are not merged in the first table above.

Styling

Tables are also styled with the help of DataTables library. The default styling class used is display. To change the styling, use parameter datatables_style, which takes either a single string with a class name, or a list of class names. Usable class names are listed in the styling reference of Datatables documentation.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    {
        "name": ["Bob", "Carol", "Alice", "Dave"],
        "age": [23, 5, 22, 54],
    }
)
pb.print_table(
    df,
    caption="Style set to 'compact'.",
    datatables_style="compact",
)
pb.print_table(
    df,
    caption="Style set to 'compact' and 'display'.",
    datatables_style=["compact", "display"],
)

Custom DataTables Configuration

Most of the parameters in the previous sections were just setting up the parameters of DataTable JavaScript object in some predefined manner. It is possible to completely override such parameters by providing custom dictionary via datatables_definition parameter. This dictionary is then serialized into JSON and passed to the DataTable JavaScript object.

import pandas as pd

import pyreball as pb

df = pd.DataFrame(
    [[row * 20 + col for col in range(20)] for row in range(40)],
    columns=[f"col_{i}" for i in range(20)],
)
datatables_definition = {
    "paging": False,
    "scrollCollapse": True,
    "scrollY": "400px",
    "searching": False,
    "order": [(1, "desc")],
}
pb.print_table(
    df,
    caption="Larger table with custom config.",
    datatables_definition=datatables_definition,
)