holoviz / holoviz/hvplot

filtering interactive dataframe with interactive boolean series / array / list not working

Open
#926 2 comments 0 reactions 2 assignees Claimed by @hoxbro View on GitHub
api: interactive
Dominant language
Python
Stars
1.4k
Forks
124
Avg merge
1d 18h
Merged PRs (30d)
1

Description

### Versions
```
hvplot 0.8.1
holoviews 1.15.1
panel 0.13.1

pandas 1.5.0
numpy 1.22.4
python 3.9.13
jupyterlab 3.4.5

Chrome Browser
```

### Description
Filtering an interactive dataframe using a comparison operator using `.loc` fails, probably due to issues with the boolean interactive dataframe that is generated as an intermediate step.

### Example
```python
import numpy as np
import pandas as pd
import hvplot.pandas
import panel as pn

df = pd.DataFrame(50*np.random.randn(10,50))

# problematic code for interactive dataframe
dfi = df.rename(columns=str).interactive(width=800) # setting column names to strings currently necessary
threshold = pn.widgets.IntSlider(start=10, end=50, value=20)
threshold # make widget

dfi.loc[:,dfi.mean() > threshold] # AttributeError:
dfi.loc[:,(dfi.mean() > threshold).values] # TypeError: 'numpy.ndarray' object is not callable
dfi.loc[:,(dfi.mean() > threshold).to_list()] # AttributeError:

# NOTE: (dfi.mean() > threshold).to_list() produces a strange repr

# equivalent code for pandas dataframe (works)
df = df.rename(columns=str)
threshold = 20
df.loc[:,df.mean() > threshold]
df.loc[:,(df.mean() > threshold).values]
df.loc[:,(df.mean() > threshold).to_list()]
```

## Stack traceback for all three cases
# case 1

```
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Input In [222], in ()
6 threshold = pnw.IntSlider(start=10, end=50, value=20, name='Spike threshold')
7 threshold
----> 9 dfi.loc[:,(dfi.mean() > threshold)]

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:624, in Interactive.__getitem__(self, other)
622 def __getitem__(self, other):
623 other = other._transform if isinstance(other, Interactive) else other
--> 624 return self._apply_operator(operator.getitem, other)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:511, in Interactive._apply_operator(self, operator, reverse, *args, **kwargs)
509 transform = new._transform
510 transform = type(transform)(transform, operator, *args, reverse=reverse)
--> 511 return new._clone(transform)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:360, in Interactive._clone(self, transform, plot, loc, center, dmap, copy, max_rows, **kwargs)
358 else:
359 kwargs = dict(self._inherit_kwargs, **dict(self._kwargs, **kwargs))
--> 360 return type(self)(self._obj, fn=self._fn, transform=transform, plot=plot, depth=depth,
361 loc=loc, center=center, dmap=dmap, _shared_obj=self._shared_obj,
362 max_rows=max_rows, **kwargs)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:266, in Interactive.__init__(self, obj, transform, fn, plot, depth, loc, center, dmap, inherit_kwargs, max_rows, method, _shared_obj, _current, **kwargs)
264 self._current = _current
265 else:
--> 266 self._current = self._transform.apply(ds, keep_index=True, compute=False)
267 self._init = True
268 self.hvplot = _hvplot(self)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:773, in dim.apply(self, dataset, flat, expanded, ranges, all_values, keep_index, compute, strict)
771 drange = ranges.get(eldim, {})
772 drange = drange.get('combined', drange)
--> 773 data = self._apply_fn(dataset, data, fn, fn_name, args,
774 kwargs, accessor, drange)
775 drop_index = keep_index_for_compute and not keep_index
776 compute = not compute_for_compute and compute

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:673, in dim._apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
671 raise e
672 else:
--> 673 data = fn(*args, **kwargs)
675 return data

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/indexing.py:1065, in _LocationIndexer.__getitem__(self, key)
1063 if type(key) is tuple:
1064 key = tuple(list(x) if is_iterator(x) else x for x in key)
-> 1065 key = tuple(com.apply_if_callable(x, self.obj) for x in key)
1066 if self._is_scalar_access(key):
1067 return self.obj._get_value(*key, takeable=self._takeable)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/indexing.py:1065, in (.0)
1063 if type(key) is tuple:
1064 key = tuple(list(x) if is_iterator(x) else x for x in key)
-> 1065 key = tuple(com.apply_if_callable(x, self.obj) for x in key)
1066 if self._is_scalar_access(key):
1067 return self.obj._get_value(*key, takeable=self._takeable)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/common.py:364, in apply_if_callable(maybe_callable, obj, **kwargs)
353 """
354 Evaluate possibly callable input using obj and kwargs if it is callable,
355 otherwise return as it is.
(...)
361 **kwargs
362 """
363 if callable(maybe_callable):
--> 364 return maybe_callable(obj, **kwargs)
366 return maybe_callable

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:480, in Interactive.__call__(self, *args, **kwargs)
478 return self._clone(*args, **kwargs)
479 # TODO: When is this error raised?
--> 480 raise AttributeError
481 elif self._method == 'plot':
482 # This - {ax: get_ax} - is passed as kwargs to the plot method in
483 # the dim expression.
484 kwargs['ax'] = self._get_ax_fn()

AttributeError:
```

# case 2

```
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [223], in ()
6 threshold = pnw.IntSlider(start=10, end=50, value=20)
7 threshold
----> 9 dfi.loc[:,(dfi.mean() > threshold).values]

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:624, in Interactive.__getitem__(self, other)
622 def __getitem__(self, other):
623 other = other._transform if isinstance(other, Interactive) else other
--> 624 return self._apply_operator(operator.getitem, other)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:511, in Interactive._apply_operator(self, operator, reverse, *args, **kwargs)
509 transform = new._transform
510 transform = type(transform)(transform, operator, *args, reverse=reverse)
--> 511 return new._clone(transform)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:360, in Interactive._clone(self, transform, plot, loc, center, dmap, copy, max_rows, **kwargs)
358 else:
359 kwargs = dict(self._inherit_kwargs, **dict(self._kwargs, **kwargs))
--> 360 return type(self)(self._obj, fn=self._fn, transform=transform, plot=plot, depth=depth,
361 loc=loc, center=center, dmap=dmap, _shared_obj=self._shared_obj,
362 max_rows=max_rows, **kwargs)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:266, in Interactive.__init__(self, obj, transform, fn, plot, depth, loc, center, dmap, inherit_kwargs, max_rows, method, _shared_obj, _current, **kwargs)
264 self._current = _current
265 else:
--> 266 self._current = self._transform.apply(ds, keep_index=True, compute=False)
267 self._init = True
268 self.hvplot = _hvplot(self)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:773, in dim.apply(self, dataset, flat, expanded, ranges, all_values, keep_index, compute, strict)
771 drange = ranges.get(eldim, {})
772 drange = drange.get('combined', drange)
--> 773 data = self._apply_fn(dataset, data, fn, fn_name, args,
774 kwargs, accessor, drange)
775 drop_index = keep_index_for_compute and not keep_index
776 compute = not compute_for_compute and compute

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:673, in dim._apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
671 raise e
672 else:
--> 673 data = fn(*args, **kwargs)
675 return data

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/indexing.py:1065, in _LocationIndexer.__getitem__(self, key)
1063 if type(key) is tuple:
1064 key = tuple(list(x) if is_iterator(x) else x for x in key)
-> 1065 key = tuple(com.apply_if_callable(x, self.obj) for x in key)
1066 if self._is_scalar_access(key):
1067 return self.obj._get_value(*key, takeable=self._takeable)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/indexing.py:1065, in (.0)
1063 if type(key) is tuple:
1064 key = tuple(list(x) if is_iterator(x) else x for x in key)
-> 1065 key = tuple(com.apply_if_callable(x, self.obj) for x in key)
1066 if self._is_scalar_access(key):
1067 return self.obj._get_value(*key, takeable=self._takeable)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/common.py:364, in apply_if_callable(maybe_callable, obj, **kwargs)
353 """
354 Evaluate possibly callable input using obj and kwargs if it is callable,
355 otherwise return as it is.
(...)
361 **kwargs
362 """
363 if callable(maybe_callable):
--> 364 return maybe_callable(obj, **kwargs)
366 return maybe_callable

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:489, in Interactive.__call__(self, *args, **kwargs)
487 method = type(new._transform)(new._transform, new._method, accessor=True)
488 kwargs = dict(new._inherit_kwargs, **kwargs)
--> 489 clone = new._clone(method(*args, **kwargs), plot=new._method == 'plot')
490 finally:
491 # If an error occurs reset _method anyway so that, e.g. the next
492 # attempt in a Notebook, is set appropriately.
493 new._method = None

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:360, in Interactive._clone(self, transform, plot, loc, center, dmap, copy, max_rows, **kwargs)
358 else:
359 kwargs = dict(self._inherit_kwargs, **dict(self._kwargs, **kwargs))
--> 360 return type(self)(self._obj, fn=self._fn, transform=transform, plot=plot, depth=depth,
361 loc=loc, center=center, dmap=dmap, _shared_obj=self._shared_obj,
362 max_rows=max_rows, **kwargs)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:266, in Interactive.__init__(self, obj, transform, fn, plot, depth, loc, center, dmap, inherit_kwargs, max_rows, method, _shared_obj, _current, **kwargs)
264 self._current = _current
265 else:
--> 266 self._current = self._transform.apply(ds, keep_index=True, compute=False)
267 self._init = True
268 self.hvplot = _hvplot(self)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:773, in dim.apply(self, dataset, flat, expanded, ranges, all_values, keep_index, compute, strict)
771 drange = ranges.get(eldim, {})
772 drange = drange.get('combined', drange)
--> 773 data = self._apply_fn(dataset, data, fn, fn_name, args,
774 kwargs, accessor, drange)
775 drop_index = keep_index_for_compute and not keep_index
776 compute = not compute_for_compute and compute

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:671, in dim._apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
669 data = method(*args, **kwargs)
670 else:
--> 671 raise e
672 else:
673 data = fn(*args, **kwargs)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:665, in dim._apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
663 else:
664 try:
--> 665 data = method(*args, **kwargs)
666 except Exception as e:
667 if 'axis' in kwargs:

TypeError: 'numpy.ndarray' object is not callable
```

# Case 3
```
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Input In [15], in ()
6 threshold = pn.widgets.IntSlider(start=10, end=50, value=20)
7 threshold
----> 9 dfi.loc[:,(dfi.mean() > threshold).to_list()]

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:624, in Interactive.__getitem__(self, other)
622 def __getitem__(self, other):
623 other = other._transform if isinstance(other, Interactive) else other
--> 624 return self._apply_operator(operator.getitem, other)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:511, in Interactive._apply_operator(self, operator, reverse, *args, **kwargs)
509 transform = new._transform
510 transform = type(transform)(transform, operator, *args, reverse=reverse)
--> 511 return new._clone(transform)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:360, in Interactive._clone(self, transform, plot, loc, center, dmap, copy, max_rows, **kwargs)
358 else:
359 kwargs = dict(self._inherit_kwargs, **dict(self._kwargs, **kwargs))
--> 360 return type(self)(self._obj, fn=self._fn, transform=transform, plot=plot, depth=depth,
361 loc=loc, center=center, dmap=dmap, _shared_obj=self._shared_obj,
362 max_rows=max_rows, **kwargs)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:266, in Interactive.__init__(self, obj, transform, fn, plot, depth, loc, center, dmap, inherit_kwargs, max_rows, method, _shared_obj, _current, **kwargs)
264 self._current = _current
265 else:
--> 266 self._current = self._transform.apply(ds, keep_index=True, compute=False)
267 self._init = True
268 self.hvplot = _hvplot(self)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:773, in dim.apply(self, dataset, flat, expanded, ranges, all_values, keep_index, compute, strict)
771 drange = ranges.get(eldim, {})
772 drange = drange.get('combined', drange)
--> 773 data = self._apply_fn(dataset, data, fn, fn_name, args,
774 kwargs, accessor, drange)
775 drop_index = keep_index_for_compute and not keep_index
776 compute = not compute_for_compute and compute

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/holoviews/util/transform.py:673, in dim._apply_fn(self, dataset, data, fn, fn_name, args, kwargs, accessor, drange)
671 raise e
672 else:
--> 673 data = fn(*args, **kwargs)
675 return data

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/indexing.py:1065, in _LocationIndexer.__getitem__(self, key)
1063 if type(key) is tuple:
1064 key = tuple(list(x) if is_iterator(x) else x for x in key)
-> 1065 key = tuple(com.apply_if_callable(x, self.obj) for x in key)
1066 if self._is_scalar_access(key):
1067 return self.obj._get_value(*key, takeable=self._takeable)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/indexing.py:1065, in (.0)
1063 if type(key) is tuple:
1064 key = tuple(list(x) if is_iterator(x) else x for x in key)
-> 1065 key = tuple(com.apply_if_callable(x, self.obj) for x in key)
1066 if self._is_scalar_access(key):
1067 return self.obj._get_value(*key, takeable=self._takeable)

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/pandas/core/common.py:364, in apply_if_callable(maybe_callable, obj, **kwargs)
353 """
354 Evaluate possibly callable input using obj and kwargs if it is callable,
355 otherwise return as it is.
(...)
361 **kwargs
362 """
363 if callable(maybe_callable):
--> 364 return maybe_callable(obj, **kwargs)
366 return maybe_callable

File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:480, in Interactive.__call__(self, *args, **kwargs)
478 return self._clone(*args, **kwargs)
479 # TODO: When is this error raised?
--> 480 raise AttributeError
481 elif self._method == 'plot':
482 # This - {ax: get_ax} - is passed as kwargs to the plot method in
483 # the dim expression.
484 kwargs['ax'] = self._get_ax_fn()

AttributeError:
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.