holoviz / hvplot

A high-level plotting API for pandas, dask, xarray, and networkx built on HoloViews
https://hvplot.holoviz.org
BSD 3-Clause "New" or "Revised" License
1.13k stars 108 forks source link

interactive DataFrame: .loc with interactive boolean Series and column not working #1009

Open JanHomann opened 1 year ago

JanHomann commented 1 year ago

Versions

hvplot = 0.8.2

Description

the .loc method can take a row plus a column parameter in Pandas. When using an interactive DataFrame, this behavior should be conserved. But when using an interactive boolean Series as the row parameter, specifying a column leads to an error message.

Example

import hvplot.pandas
from bokeh.sampledata.penguins import data as df

dfi = df.interactive()

# ERROR
dfi.loc[dfi['body_mass_g'] > 4000,'bill_length_mm']         #  interactive boolean Series + column

On the other hand, those slight modifications all work.

# normal DataFrame: works
df.loc[df['body_mass_g'] > 4000,'bill_length_mm']           # works: no interactive DataFrame

# interactive DataFrame: variations that work
dfi.loc[[10,11,12],'bill_length_mm']                        # works: list + column
dfi.loc[dfi['body_mass_g'] > 4000]                          # works: interactive boolean Series
dfi.loc[df['body_mass_g'] > 4000,'bill_length_mm']          # works: normal boolean Series + column
dfi.loc[dfi['body_mass_g'] > 4000]['bill_length_mm']        # works: interactive boolean Series, column selected on output

Traceback

``` --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Input In [33], in () 4 df.loc[df['body_mass_g'] > 4000,'bill_length_mm'] 6 dfi = df.interactive() ----> 8 dfi.loc[dfi['body_mass_g'] > 4000,'bill_length_mm'] File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:634, in Interactive.__getitem__(self, other) 632 def __getitem__(self, other): 633 other = other._transform if isinstance(other, Interactive) else other --> 634 return self._apply_operator(operator.getitem, other) File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:521, in Interactive._apply_operator(self, operator, reverse, *args, **kwargs) 519 transform = new._transform 520 transform = type(transform)(transform, operator, *args, reverse=reverse) --> 521 return new._clone(transform) File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:370, in Interactive._clone(self, transform, plot, loc, center, dmap, copy, max_rows, **kwargs) 368 else: 369 kwargs = dict(self._inherit_kwargs, **dict(self._kwargs, **kwargs)) --> 370 return type(self)(self._obj, fn=self._fn, transform=transform, plot=plot, depth=depth, 371 loc=loc, center=center, dmap=dmap, _shared_obj=self._shared_obj, 372 max_rows=max_rows, **kwargs) File ~/Dropbox/Berry-Vaziri-Collaboration/.venv/lib/python3.9/site-packages/hvplot/interactive.py:276, in Interactive.__init__(self, obj, transform, fn, plot, depth, loc, center, dmap, inherit_kwargs, max_rows, method, _shared_obj, _current, **kwargs) 274 self._current = _current 275 else: --> 276 self._current = self._transform.apply(ds, keep_index=True, compute=False) 277 self._init = True 278 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:490, in Interactive.__call__(self, *args, **kwargs) 488 return self._clone(*args, **kwargs) 489 # TODO: When is this error raised? --> 490 raise AttributeError 491 elif self._method == 'plot': 492 # This - {ax: get_ax} - is passed as kwargs to the plot method in 493 # the dim expression. 494 kwargs['ax'] = self._get_ax_fn() AttributeError: ```
JanHomann commented 1 year ago

This is very much related to my previous issue #926.

In the tests that I show here, it becomes clear that interactive boolean Series as input to .loc actually does work, but that the actual issue is the simultaneous specification of rows and columns (with one being an interactive boolean Series). Maybe both issues should be merged somehow?

maximlt commented 1 year ago

Thanks for the bug report! Indeed the two issues look similar, I think it's ok to keep them both open until someone digs into that and finds out whether they have the exact same root cause. Hoping to spend more time on hvPlot once Panel 1.0 is released :)

JanHomann commented 1 year ago

@maximlt Seems to work now as far as I can see. Close the issue?