Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 7 additions & 3 deletions hvplot/plotting/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
panel_available = False

from ..converter import HoloViewsConverter
from ..util import process_dynamic_args
from ..util import is_list_like, process_dynamic_args


class hvPlotBase:
Expand All @@ -33,8 +33,8 @@ def __call__(self, x=None, y=None, kind=None, **kwds):

Parameters
----------
x, y : string, optional
Field name in the data to draw x- and y-positions from
x, y : string, list, or array-like, optional
Field name(s) in the data to draw x- and y-positions from
kind : string, optional
The kind of plot to generate, e.g. 'line', 'scatter', etc.
**kwds : optional
Expand All @@ -44,6 +44,10 @@ def __call__(self, x=None, y=None, kind=None, **kwds):
-------
HoloViews object: Object representing the requested visualization
"""
# Convert an array-like to a list
x = list(x) if is_list_like(x) else x
y = list(y) if is_list_like(y) else y

if isinstance(kind, str) and kind not in self.__all__:
raise NotImplementedError("kind='{kind}' for data of type {type}".format(
kind=kind, type=type(self._data)))
Expand Down
21 changes: 21 additions & 0 deletions hvplot/tests/plotting/testcore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import numpy as np
import pandas as pd
import hvplot.pandas # noqa

import pytest

@pytest.mark.parametrize("y", (
["A", "B", "C", "D"],
("A", "B", "C", "D"),
{"A", "B", "C", "D"},
np.array(["A", "B", "C", "D"]),
pd.Index(["A", "B", "C", "D"]),
pd.Series(["A", "B", "C", "D"]),
))
def test_diffent_input_types(y):
df = pd._testing.makeDataFrame()
types = {t for t in dir(df.hvplot) if not t.startswith("_")}
ignore_types = {'bivariate', 'heatmap', 'hexbin', 'labels', 'vectorfield'}

for t in types - ignore_types:
df.hvplot(y=y, kind=t)
15 changes: 14 additions & 1 deletion hvplot/tests/testutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import sys

import numpy as np
import pandas as pd
import pytest

from unittest import TestCase, SkipTest

from hvplot.util import check_crs, process_xarray
from hvplot.util import check_crs, is_list_like, process_xarray


class TestProcessXarray(TestCase):
Expand Down Expand Up @@ -275,3 +276,15 @@ def test_check_crs():
assert p.srs == '+proj=utm +zone=15 +datum=NAD83 +units=m +no_defs'
p = check_crs('wrong')
assert p is None


def test_is_list_like():
assert not is_list_like(0)
assert not is_list_like('string')
assert not is_list_like(np.array('a'))
assert is_list_like(['a', 'b'])
assert is_list_like(('a', 'b'))
assert is_list_like({'a', 'b'})
assert is_list_like(pd.Series(['a', 'b']))
assert is_list_like(pd.Index(['a', 'b']))
assert is_list_like(np.array(['a', 'b']))
16 changes: 16 additions & 0 deletions hvplot/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from packaging.version import Version
from types import FunctionType

import numpy as np
import pandas as pd
import holoviews as hv
import param
Expand Down Expand Up @@ -252,6 +253,21 @@ def process_crs(crs):
raise ValueError("Projection must be defined as a EPSG code, proj4 string, cartopy CRS or pyproj.Proj.")
return crs


def is_list_like(obj):
"""
Adapted from pandas' is_list_like cython function.
"""
return (
# equiv: `isinstance(obj, abc.Iterable)`
hasattr(obj, "__iter__") and not isinstance(obj, type)
# we do not count strings/unicode/bytes as list-like
and not isinstance(obj, (str, bytes))
# exclude zero-dimensional numpy arrays, effectively scalars
and not (isinstance(obj, np.ndarray) and obj.ndim == 0)
)


def is_tabular(data):
if check_library(data, ['dask', 'streamz', 'pandas', 'geopandas', 'cudf']):
return True
Expand Down