Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polars in hvplot.plot: avoid registering the hvplot accessor and simple test #1222

Merged
merged 2 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hvplot/plotting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def plot(data, kind, **kwargs):
no_none_kwargs[k] = v

if is_polars(data):
from hvplot.polars import hvPlotTabularPolars
from .core import hvPlotTabularPolars
return hvPlotTabularPolars(data)(kind=kind, **no_none_kwargs)
return hvPlotTabular(data)(kind=kind, **no_none_kwargs)

Expand Down
42 changes: 42 additions & 0 deletions hvplot/plotting/core.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import itertools
from collections import defaultdict

import param
Expand Down Expand Up @@ -1862,6 +1863,47 @@ def labels(self, x=None, y=None, text=None, **kwds):
return self(x, y, text=text, kind="labels", **kwds)


class hvPlotTabularPolars(hvPlotTabular):
def _get_converter(self, x=None, y=None, kind=None, **kwds):
import polars as pl

params = dict(self._metadata, **kwds)
x = x or params.pop("x", None)
y = y or params.pop("y", None)
kind = kind or params.pop("kind", None)

# Find columns which should be converted for LazyDataFrame and DataFrame
if isinstance(self._data, (pl.LazyFrame, pl.DataFrame)):
if params.get("hover_cols") == "all":
columns = list(self._data.columns)
else:
possible_columns = [
[v] if isinstance(v, str) else v
for v in params.values()
if isinstance(v, (str, list))
]
columns = (
set(self._data.columns) & set(itertools.chain(*possible_columns))
) or {self._data.columns[0]}
xs = x if is_list_like(x) else (x,)
ys = y if is_list_like(y) else (y,)
columns |= {*xs, *ys}
columns.discard(None)

if isinstance(self._data, pl.DataFrame):
data = self._data.select(columns).to_pandas()
elif isinstance(self._data, pl.Series):
data = self._data.to_pandas()
elif isinstance(self._data, pl.LazyFrame):
data = self._data.select(columns).collect().to_pandas()
else:
raise ValueError(
"Only Polars DataFrame, Series, and LazyFrame are supported"
)

return HoloViewsConverter(data, x, y, kind=kind, **params)


class hvPlot(hvPlotTabular):
"""
The plotting method: `df.hvplot(...)` creates a plot similarly to the familiar Pandas
Expand Down
48 changes: 2 additions & 46 deletions hvplot/polars.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,6 @@
"""Adds the `.hvplot` method to pl.DataFrame, pl.LazyFrame and pl.Series"""
import itertools

from hvplot import hvPlotTabular, post_patch
from hvplot.converter import HoloViewsConverter
from hvplot.util import is_list_like


class hvPlotTabularPolars(hvPlotTabular):
def _get_converter(self, x=None, y=None, kind=None, **kwds):
import polars as pl

params = dict(self._metadata, **kwds)
x = x or params.pop("x", None)
y = y or params.pop("y", None)
kind = kind or params.pop("kind", None)

# Find columns which should be converted for LazyDataFrame and DataFrame
if isinstance(self._data, (pl.LazyFrame, pl.DataFrame)):
if params.get("hover_cols") == "all":
columns = list(self._data.columns)
else:
possible_columns = [
[v] if isinstance(v, str) else v
for v in params.values()
if isinstance(v, (str, list))
]
columns = (
set(self._data.columns) & set(itertools.chain(*possible_columns))
) or {self._data.columns[0]}
xs = x if is_list_like(x) else (x,)
ys = y if is_list_like(y) else (y,)
columns |= {*xs, *ys}
columns.discard(None)

if isinstance(self._data, pl.DataFrame):
data = self._data.select(columns).to_pandas()
elif isinstance(self._data, pl.Series):
data = self._data.to_pandas()
elif isinstance(self._data, pl.LazyFrame):
data = self._data.select(columns).collect().to_pandas()
else:
raise ValueError(
"Only Polars DataFrame, Series, and LazyFrame are supported"
)

return HoloViewsConverter(data, x, y, kind=kind, **params)
from hvplot import post_patch
from hvplot.plotting.core import hvPlotTabularPolars


def patch(name="hvplot", extension="bokeh", logo=False):
Expand Down
21 changes: 19 additions & 2 deletions hvplot/tests/testplotting.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
"""
Tests pandas.options.backend setting
"""
from packaging.version import Version
from unittest import TestCase, SkipTest

import holoviews as hv
import pandas as pd
import pytest

from packaging.version import Version
from parameterized import parameterized

from ..converter import HoloViewsConverter
from hvplot.converter import HoloViewsConverter
from hvplot.plotting import plot

try:
import polars as pl
skip_polar = False
except ImportError:
skip_polar = True


no_args = ['line', 'area', 'hist', 'box', 'kde', 'density', 'bar', 'barh']
Expand Down Expand Up @@ -58,3 +68,10 @@ def setUp(self):
raise SkipTest('entrypoints for plotting.backends was added '
'in pandas 0.25.1')
pd.options.plotting.backend = 'hvplot'


@pytest.mark.skipif(skip_polar, reason="polars not installed")
def test_plot_supports_polars():
dfp = pl.DataFrame(pd._testing.makeDataFrame())
maximlt marked this conversation as resolved.
Show resolved Hide resolved
out = plot(dfp, 'line')
assert isinstance(out, hv.Curve)