import datetime as dt
import numpy as np
import pandas as pd
import panel as pn
np.random.seed(7)
pn.extension('tabulator', css_files=[pn.io.resources.CSS_URLS['font-awesome']])
df = pd.DataFrame({
'int': [1, 2, 3],
'float': [3.14, 6.28, 9.42],
'str': ['A', 'B', 'C'],
'bool': [True, False, True],
'date': [dt.date(2019, 1, 1), dt.date(2020, 1, 1), dt.date(2020, 1, 10)],
'datetime': [dt.datetime(2019, 1, 1, 10), dt.datetime(2020, 1, 1, 12), dt.datetime(2020, 1, 10, 13)]
}, index=[1, 2, 3])
df_widget = pn.widgets.Tabulator(df, buttons={'Print': ""})
df_widget
from bokeh.models.widgets.tables import NumberFormatter, BooleanFormatter
bokeh_formatters = {
'float': NumberFormatter(format='0.00000'),
'bool': BooleanFormatter(),
}
pn.widgets.Tabulator(df, formatters=bokeh_formatters)
tabulator_formatters = {
'float': {'type': 'progress', 'max': 10},
'bool': {'type': 'tickCross'}
}
pn.widgets.Tabulator(df, formatters=tabulator_formatters)
from bokeh.models.widgets.tables import CheckboxEditor, NumberEditor, SelectEditor, DateEditor, TimeEditor
bokeh_editors = {
'float': NumberEditor(),
'bool': CheckboxEditor(),
'str': SelectEditor(options=['A', 'B', 'C', 'D']),
}
pn.widgets.Tabulator(df[['float', 'bool', 'str']], editors=bokeh_editors)
tabulator_editors = {
'int': None,
'float': {'type': 'number', 'max': 10, 'step': 0.1},
'bool': {'type': 'tickCross', 'tristate': True, 'indeterminateValue': None},
'str': {'type': 'autocomplete', 'values': True},
'date': 'date',
'datetime': 'datetime'
}
edit_table = pn.widgets.Tabulator(df, editors=tabulator_editors)
edit_table
edit_table.on_edit(lambda e: print(e.column, e.row, e.old, e.value))
custom_df = pd._testing.makeMixedDataFrame().iloc[:3, :]
pn.widgets.Tabulator(custom_df, widths={'index': 70, 'A': 50, 'B': 50, 'C': 70, 'D': 130})
pn.widgets.Tabulator(custom_df, widths=130)
pn.widgets.Tabulator(custom_df, widths={'index': '5%', 'A': '15%', 'B': '15%', 'C': '25%', 'D': '40%'}, sizing_mode='stretch_width')
pn.widgets.Tabulator(custom_df, layout='fit_data', width=400)
pn.widgets.Tabulator(custom_df, layout='fit_data_stretch', width=400)
pn.widgets.Tabulator(custom_df, layout='fit_data_fill', width=400)
pn.widgets.Tabulator(custom_df, layout='fit_data_table')
pn.widgets.Tabulator(custom_df, layout='fit_columns', width=650)
pn.widgets.Tabulator(df.iloc[:, :2], header_align='center', text_align={'int': 'center', 'float': 'left'}, widths=150)
style_df = pd.DataFrame(np.random.randn(4, 5), columns=list('ABCDE'))
styled = pn.widgets.Tabulator(style_df)
def color_negative_red(val):
"""
Takes a scalar and returns a string with
the css property `'color: red'` for negative
strings, black otherwise.
"""
color = 'red' if val < 0 else 'black'
return 'color: %s' % color
def highlight_max(s):
'''
highlight the maximum in a Series yellow.
'''
is_max = s == s.max()
return ['background-color: yellow' if v else '' for v in is_max]
styled.style.applymap(color_negative_red).apply(highlight_max)
styled
sel_df = pd.DataFrame(np.random.randn(3, 5), columns=list('ABCDE'))
select_table = pn.widgets.Tabulator(sel_df, selection=[0, 2])
select_table
select_table.selection = [1]
select_table.selected_dataframe
pn.widgets.Tabulator(sel_df, selection=[0, 2], selectable='checkbox')
select_table = pn.widgets.Tabulator(sel_df, selectable_rows=lambda df: list(range(0, len(df), 2)))
select_table
def click(event):
print(f'Clicked cell in {event.column!r} column, row {event.row!r} with value {event.value!r}')
select_table.on_click(click)
# Optionally we can also limit the callback to a specific column
# select_table.on_click(click, column='A')
wide_df = pd._testing.makeCustomDataframe(3, 10, r_idx_names=['index'])
pn.widgets.Tabulator(wide_df, frozen_columns=['index'], width=400)
date_df = pd._testing.makeTimeDataFrame().iloc[:5, :2]
agg_df = pd.concat([date_df, date_df.median().to_frame('Median').T, date_df.mean().to_frame('Mean').T])
agg_df.index= agg_df.index.map(str)
pn.widgets.Tabulator(agg_df, frozen_rows=[-2, -1], height=200)
from bokeh.sampledata.periodic_table import elements
periodic_df = elements[['atomic number', 'name', 'atomic mass', 'metal', 'year discovered']].set_index('atomic number')
content_fn = lambda row: pn.pane.HTML(
f'',
sizing_mode='stretch_width'
)
periodic_table = pn.widgets.Tabulator(
periodic_df, height=350, layout='fit_columns', sizing_mode='stretch_width',
row_content=content_fn, embed_content=True
)
periodic_table
periodic_table.expanded
pn.widgets.Tabulator(date_df.iloc[:3], groups={'Group 1': ['A', 'B'], 'Group 2': ['C', 'D']})
from bokeh.sampledata.autompg import autompg
pn.widgets.Tabulator(autompg, groupby=['yr', 'origin'], height=240)
from bokeh.sampledata.population import data as population_data
pop_df = population_data[population_data.Year == 2020].set_index(['Location', 'AgeGrp', 'Sex'])[['Value']]
pn.widgets.Tabulator(value=pop_df, hierarchical=True, aggregators={'Sex': 'sum', 'AgeGrp': 'sum'}, height=200)
large_df = pd._testing.makeCustomDataframe(100000, 5)
pn.widgets.Tabulator(large_df, pagination='remote', page_size=3)
medium_df = pd._testing.makeCustomDataframe(1000, 5)
pn.widgets.Tabulator(medium_df, pagination='local', page_size=3)
filter_table = pn.widgets.Tabulator(pd._testing.makeMixedDataFrame())
filter_table
filter_table.add_filter((0, 3), 'A')
slider = pn.widgets.RangeSlider(start=0, end=3, name='A Filter')
filter_table.add_filter(slider, 'A')
select = pn.widgets.MultiSelect(options=['foo1', 'foo2', 'foo3', 'foo4', 'foo5'], name='C Filter')
filter_table.add_filter(select, 'C')
pn.Row(
pn.Column(slider, select),
filter_table
)
select.value = ['foo1', 'foo2']
filter_table.current_view
import sqlite3
from bokeh.sampledata.movies_data import movie_path
con = sqlite3.Connection(movie_path)
movies_df = pd.read_sql('SELECT Title, Year, Genre, Director, Writer, imdbRating from omdb', con)
movies_df = movies_df[~movies_df.Director.isna()]
movies_table = pn.widgets.Tabulator(movies_df, pagination='remote', page_size=4)
director_filter = pn.widgets.TextInput(name='Director filter', value='Chaplin')
def contains_filter(df, pattern, column):
if not pattern:
return df
return df[df[column].str.contains(pattern)]
movies_table.add_filter(pn.bind(contains_filter, pattern=director_filter, column='Director'))
pn.Row(director_filter, movies_table)
tabulator_editors = {
'float': {'type': 'number', 'max': 10, 'step': 0.1},
'bool': {'type': 'tickCross', 'tristate': True, 'indeterminateValue': None},
'str': {'type': 'autocomplete', 'values': True}
}
header_filter_table = pn.widgets.Tabulator(
df[['float', 'bool', 'str']], height=140, width=400, layout='fit_columns',
editors=tabulator_editors, header_filters=True
)
header_filter_table
header_filter_table.filters
movie_filters = {
'Title': {'type': 'input', 'func': 'like', 'placeholder': 'Enter title'},
'Year': {'placeholder': 'Enter year'},
'Genre': {'type': 'input', 'func': 'like', 'placeholder': 'Enter genre'},
'Director': {'type': 'input', 'func': 'like', 'placeholder': 'Enter director'},
'Writer': {'type': 'input', 'func': 'like', 'placeholder': 'Enter writer'},
'imdbRating': {'type': 'number', 'func': '>=', 'placeholder': 'Enter minimum rating'}
}
filter_table = pn.widgets.Tabulator(
movies_df, pagination='remote', layout='fit_columns', page_size=4, sizing_mode='stretch_width',
header_filters=movie_filters
)
filter_table
download_df = pd.DataFrame(np.random.randn(4, 5), columns=list('ABCDE'))
download_table = pn.widgets.Tabulator(download_df)
filename, button = download_table.download_menu(
text_kwargs={'name': 'Enter filename', 'value': 'default.csv'},
button_kwargs={'name': 'Download table'}
)
pn.Row(
pn.Column(filename, button),
download_table
)
button_table = pn.widgets.Tabulator(df, buttons={
'print': '',
'check': ''
})
string = pn.widgets.StaticText()
button_table.on_click(
lambda e: string.param.update(value=f'Clicked {e.column!r} on row {e.row}')
)
pn.Row(button_table, string)
stream_df = pd.DataFrame(np.random.randn(5, 5), columns=list('ABCDE'))
stream_table = pn.widgets.Tabulator(stream_df, layout='fit_columns', width=450, height=400)
stream_table
def stream_data(follow=True):
stream_df = pd.DataFrame(np.random.randn(5, 5), columns=list('ABCDE'))
stream_table.stream(stream_df, follow=follow)
pn.state.add_periodic_callback(stream_data, period=1000, count=5);
stream_data(follow=False)
patch_table = pn.widgets.Tabulator(df[['int', 'float', 'str', 'bool']])
patch_table
patch_table.patch({
'bool': [
(0, False),
(2, False)
],
'int': [
(slice(0, 2), [3, 2])
]
})
df = pd.DataFrame({
'int': [1, 2, 3],
'float': [3.14, 6.28, 9.42],
'str': ['A', 'B', 'C'],
'bool': [True, False, True],
'date': [dt.date(2019, 1, 1), dt.date(2020, 1, 1), dt.date(2020, 1, 10)]
}, index=[1, 2, 3])
pn.widgets.Tabulator(df, configuration={
'resizableColumns': False,
'headerSort': False
})