From d7a6b668fc8fd83685fef196bde963b0966fd6f1 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 1 Apr 2022 13:29:09 +0200 Subject: [PATCH] Implement keywords filter for Tabulator (#3298) --- panel/tests/widgets/test_tables.py | 41 ++++++++++++++++++++++++++++++ panel/widgets/tables.py | 13 ++++++++++ 2 files changed, 54 insertions(+) diff --git a/panel/tests/widgets/test_tables.py b/panel/tests/widgets/test_tables.py index 8d4af693b8..24427443f1 100644 --- a/panel/tests/widgets/test_tables.py +++ b/panel/tests/widgets/test_tables.py @@ -1327,6 +1327,47 @@ def test_tabulator_constant_list_filter_client_side(document, comm): np.testing.assert_array_equal(values, expected[col]) +def test_tabulator_keywords_filter_client_side(document, comm): + df = makeMixedDataFrame() + table = Tabulator(df) + + model = table.get_root(document, comm) + + table.filters = [{'field': 'C', 'type': 'keywords', 'value': 'foo3 foo5'}] + + expected = { + 'index': np.array([2, 4]), + 'A': np.array([2, 4]), + 'B': np.array([0, 0]), + 'C': np.array(['foo3', 'foo5']), + 'D': np.array(['2009-01-05T00:00:00.000000000', + '2009-01-07T00:00:00.000000000'], + dtype='datetime64[ns]').astype(np.int64) / 10e5 + } + for col, values in model.source.data.items(): + np.testing.assert_array_equal(values, expected[col]) + + +def test_tabulator_keywords_match_all_filter_client_side(document, comm): + df = makeMixedDataFrame() + table = Tabulator(df, header_filters={'C': {'type': 'input', 'func': 'keywords', 'matchAll': True}}) + + model = table.get_root(document, comm) + + table.filters = [{'field': 'C', 'type': 'keywords', 'value': 'f oo 3'}] + + expected = { + 'index': np.array([2]), + 'A': np.array([2]), + 'B': np.array([0]), + 'C': np.array(['foo3']), + 'D': np.array(['2009-01-05T00:00:00.000000000'], + dtype='datetime64[ns]').astype(np.int64) / 10e5 + } + for col, values in model.source.data.items(): + np.testing.assert_array_equal(values, expected[col]) + + def test_tabulator_widget_scalar_filter(document, comm): df = makeMixedDataFrame() table = Tabulator(df) diff --git a/panel/widgets/tables.py b/panel/widgets/tables.py index 6fd426b4af..c6c355c680 100644 --- a/panel/widgets/tables.py +++ b/panel/widgets/tables.py @@ -309,6 +309,7 @@ def _filter_dataframe(self, df): col_name = filt['field'] op = filt['type'] val = filt['value'] + filt_def = getattr(self, 'header_filters', {}) or {} if col_name in df.columns: col = df[col_name] elif col_name in self.indexes: @@ -345,6 +346,18 @@ def _filter_dataframe(self, df): filters.append(col.str.startsWith(val)) elif op == 'ends': filters.append(col.str.endsWith(val)) + elif op == 'keywords': + match_all = filt_def.get(col_name, {}).get('matchAll', False) + sep = filt_def.get(col_name, {}).get('separator', ' ') + matches = val.lower().split(sep) + if match_all: + for match in matches: + filters.append(col.str.lower().str.contains(match)) + else: + filt = col.str.lower().str.contains(matches[0]) + for match in matches[1:]: + filt |= col.str.lower().str.contains(match) + filters.append(filt) elif op == 'regex': raise ValueError("Regex filtering not supported.") else: