panel icon indicating copy to clipboard operation
panel copied to clipboard

`selected_dataframe` is linked to the `current_view`

Open maximlt opened this issue 3 years ago • 2 comments

The selected_dataframe property is computed based on the current_view, which can return wrong data or raise an error if some filters are applied. I think the selected_dataframe should not be linked to the current_view, it seems useful in a large table to be able to filter (and sort) and select rows at the same time.

maximlt avatar Jul 04 '22 17:07 maximlt

I think I just run into this because selected_dataframe returns self.current_view.iloc[self.selection], and self.selection indexs the original dataframe and not self.current_view.

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/panel/widgets/tables.py:839](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/panel/widgets/tables.py:839), in BaseTable.selected_dataframe(self)
    837 if not self.selection:
    838     return self.current_view.iloc[:0]
--> 839 return self.current_view.iloc[self.selection]

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1073](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1073), in _LocationIndexer.__getitem__(self, key)
   1070 axis = self.axis or 0
   1072 maybe_callable = com.apply_if_callable(key, self.obj)
-> 1073 return self._getitem_axis(maybe_callable, axis=axis)

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1616](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1616), in _iLocIndexer._getitem_axis(self, key, axis)
   1614 # a list of integers
   1615 elif is_list_like_indexer(key):
-> 1616     return self._get_list_axis(key, axis=axis)
   1618 # a single integer
   1619 else:
   1620     key = item_from_zerodim(key)

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1590](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1590), in _iLocIndexer._get_list_axis(self, key, axis)
   1587     return self.obj._take_with_is_copy(key, axis=axis)
   1588 except IndexError as err:
   1589     # re-raise with different error message
-> 1590     raise IndexError("positional indexers are out-of-bounds") from err

IndexError: positional indexers are out-of-bounds

peterroelants avatar Sep 26 '23 16:09 peterroelants

To understand what happens you can play with the code below.

import panel as pn
import pandas as pd
import random
from datetime import datetime, timedelta

pn.extension("tabulator", template="fast")

df = pd.DataFrame({
    "x": [1,3,2],
    "y": ["a", "b", "c"]
})

table = pn.widgets.Tabulator(df, sizing_mode="stretch_both", selectable='checkbox', height=300)
update = pn.widgets.Button(name="Update")

@pn.depends(update)
def result(event):
    iloc = df.iloc[table.selection,:]
    loc = df.loc[table.selection,:]

    return pn.Row(
        pn.Column("df", df), 
        pn.Column("table.current_view", table.current_view),
        pn.Column("table.selection", table.selection),
        pn.Column("selected_dataframe", table.selected_dataframe), 
        pn.Column("df.iloc", iloc), 
        pn.Column("df.loc", loc),
        pn.Column("table.current_view.iloc", table.current_view.iloc[table.selection,:]), 
        pn.Column("table.current_view.loc", table.current_view.loc[table.selection,:]),
    )

pn.Column(update, table, result).servable()

As long as the user has not sorted Tabulator things works.

image

But if we sort (on column x) things gets out of sync.

image

I think was it not clearly documented is that selection returns the selected indicies from the index.

image

At least for our use case using df.loc[table.selection] instead of table.selected_dataframe will work.

MarcSkovMadsen avatar Feb 27 '24 08:02 MarcSkovMadsen

I think I just run into this because selected_dataframe returns self.current_view.iloc[self.selection], and self.selection indexs the original dataframe and not self.current_view.

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/panel/widgets/tables.py:839](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/panel/widgets/tables.py:839), in BaseTable.selected_dataframe(self)
    837 if not self.selection:
    838     return self.current_view.iloc[:0]
--> 839 return self.current_view.iloc[self.selection]

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1073](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1073), in _LocationIndexer.__getitem__(self, key)
   1070 axis = self.axis or 0
   1072 maybe_callable = com.apply_if_callable(key, self.obj)
-> 1073 return self._getitem_axis(maybe_callable, axis=axis)

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1616](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1616), in _iLocIndexer._getitem_axis(self, key, axis)
   1614 # a list of integers
   1615 elif is_list_like_indexer(key):
-> 1616     return self._get_list_axis(key, axis=axis)
   1618 # a single integer
   1619 else:
   1620     key = item_from_zerodim(key)

File [~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1590](https://file+.vscode-resource.vscode-cdn.net/home/peter/workspace/lcms_polymer_model/notebooks/peter/aspect_platform/apps/~/mambaforge/envs/lcms_polymer_env/lib/python3.11/site-packages/pandas/core/indexing.py:1590), in _iLocIndexer._get_list_axis(self, key, axis)
   1587     return self.obj._take_with_is_copy(key, axis=axis)
   1588 except IndexError as err:
   1589     # re-raise with different error message
-> 1590     raise IndexError("positional indexers are out-of-bounds") from err

IndexError: positional indexers are out-of-bounds

This happens when filtering is applied as well. Not just on sorting. So, the main problem is in the .selection I believe. When the filtering is applied, the .selection doesn't return the correct integer index.

Cyb3r-Monk avatar Jul 17 '24 11:07 Cyb3r-Monk

This happens when filtering is applied as well. Not just on sorting. So, the main problem is in the .selection I believe. When the filtering is applied, the .selection doesn't return the correct integer index.

As discussed in #6997, the .selection very intentionally uses integer indexes relative to the original data. This is definitely wrong self.current_view.iloc[self.selection].

philippjfr avatar Jul 22 '24 16:07 philippjfr

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Sep 09 '25 18:09 github-actions[bot]