diff --git a/holoviews/core/data/array.py b/holoviews/core/data/array.py index ee0e279a46..26b3abecf5 100644 --- a/holoviews/core/data/array.py +++ b/holoviews/core/data/array.py @@ -45,6 +45,8 @@ def init(cls, eltype, data, kdims, vdims): data = np.column_stack(data) else: raise ValueError('ArrayInterface expects data to be of uniform shape.') + elif isinstance(data, list) and data == []: + data = np.empty((0,len(dimensions))) elif not isinstance(data, np.ndarray): data = np.array([], ndmin=2).T if data is None else list(data) try: diff --git a/holoviews/core/data/dask.py b/holoviews/core/data/dask.py index 2198e3e069..696e417679 100644 --- a/holoviews/core/data/dask.py +++ b/holoviews/core/data/dask.py @@ -178,7 +178,7 @@ def aggregate(cls, columns, dimensions, function, **kwargs): inbuilts = {'amin': 'min', 'amax': 'max', 'mean': 'mean', 'std': 'std', 'sum': 'sum', 'var': 'var'} if len(dimensions): - groups = reindexed.groupby(cols, sort=False) + groups = reindexed.groupby(cols) if (function.__name__ in inbuilts): agg = getattr(groups, inbuilts[function.__name__])() else: diff --git a/holoviews/core/data/dictionary.py b/holoviews/core/data/dictionary.py index 2fdcf7f3f3..7668f54898 100644 --- a/holoviews/core/data/dictionary.py +++ b/holoviews/core/data/dictionary.py @@ -54,6 +54,8 @@ def init(cls, eltype, data, kdims, vdims): else: data = np.atleast_2d(data).T data = {k: data[:,i] for i,k in enumerate(dimensions)} + elif isinstance(data, list) and data == []: + data = OrderedDict([(d, []) for d in dimensions]) elif isinstance(data, list) and np.isscalar(data[0]): data = {dimensions[0]: np.arange(len(data)), dimensions[1]: data} elif (isinstance(data, list) and isinstance(data[0], tuple) and len(data[0]) == 2 diff --git a/holoviews/core/data/grid.py b/holoviews/core/data/grid.py index 6c237ade71..0c0736f737 100644 --- a/holoviews/core/data/grid.py +++ b/holoviews/core/data/grid.py @@ -50,10 +50,14 @@ def init(cls, eltype, data, kdims, vdims): raise ValueError('GridInterface interface requires at least ' 'one value dimension.') + ndims = len(kdims) dimensions = [d.name if isinstance(d, Dimension) else d for d in kdims + vdims] if isinstance(data, tuple): data = {d: v for d, v in zip(dimensions, data)} + elif isinstance(data, list) and data == []: + data = {d: np.array([]) for d in dimensions[:ndims]} + data.update({d: np.empty((0,) * ndims) for d in dimensions[ndims:]}) elif not isinstance(data, dict): raise TypeError('GridInterface must be instantiated as a ' 'dictionary or tuple') diff --git a/holoviews/core/data/iris.py b/holoviews/core/data/iris.py index 195ae19f7b..f130ab6154 100644 --- a/holoviews/core/data/iris.py +++ b/holoviews/core/data/iris.py @@ -87,7 +87,14 @@ def init(cls, eltype, data, kdims, vdims): if isinstance(data, tuple): value_array = data[-1] data = {d: vals for d, vals in zip(kdim_names + [vdim.name], data)} - elif isinstance(data, dict): + elif isinstance(data, list) and data == []: + ndims = len(kdims) + dimensions = [d.name if isinstance(d, Dimension) else + d for d in kdims + vdims] + data = {d: np.array([]) for d in dimensions[:ndims]} + data.update({d: np.empty((0,) * ndims) for d in dimensions[ndims:]}) + + if isinstance(data, dict): value_array = data[vdim.name] coords = [(iris.coords.DimCoord(data[kd.name], long_name=kd.name, units=kd.unit), ndims-n-1) diff --git a/holoviews/core/data/pandas.py b/holoviews/core/data/pandas.py index 0a8826f10e..85c55102ae 100644 --- a/holoviews/core/data/pandas.py +++ b/holoviews/core/data/pandas.py @@ -67,6 +67,8 @@ def init(cls, eltype, data, kdims, vdims): data = np.atleast_2d(data).T else: data = tuple(data[:, i] for i in range(data.shape[1])) + elif isinstance(data, list) and data == []: + data = None if isinstance(data, tuple): data = [np.array(d) if not isinstance(d, np.ndarray) else d for d in data] diff --git a/holoviews/core/data/xarray.py b/holoviews/core/data/xarray.py index caf9a42f6c..e9b21a9897 100644 --- a/holoviews/core/data/xarray.py +++ b/holoviews/core/data/xarray.py @@ -58,6 +58,12 @@ def init(cls, eltype, data, kdims, vdims): for vd in vdims] if isinstance(data, tuple): data = {d.name: vals for d, vals in zip(kdims + vdims, data)} + elif isinstance(data, list) and data == []: + ndims = len(kdims) + dimensions = [d.name if isinstance(d, Dimension) else + d for d in kdims + vdims] + data = {d: np.array([]) for d in dimensions[:ndims]} + data.update({d: np.empty((0,) * ndims) for d in dimensions[ndims:]}) if not isinstance(data, dict): raise TypeError('XArrayInterface could not interpret data type') coords = [(kd.name, data[kd.name]) for kd in kdims][::-1] diff --git a/tests/testdataset.py b/tests/testdataset.py index da2d891011..b305f081da 100644 --- a/tests/testdataset.py +++ b/tests/testdataset.py @@ -101,6 +101,11 @@ def test_dataset_dataframe_init_hm_alias(self): kdims=[('x', 'X-label')], vdims=[('x2', 'X2-label')]) self.assertTrue(isinstance(dataset.data, self.data_instance_type)) + def test_dataset_empty_list_init(self): + dataset = Dataset([], kdims=['x'], vdims=['y']) + for d in 'xy': + self.assertEqual(dataset.dimension_values(d), np.array([])) + # Properties and information def test_dataset_shape(self): @@ -613,6 +618,12 @@ def setUp(self): # Literal formats that have been previously been supported but # currently are only supported via NdElement. + def test_dataset_empty_list_init(self): + """ + Will soon be deprecated, new features not supported + """ + raise SkipTest("Not supported") + def test_dataset_double_zip_init(self): dataset = Dataset(zip(zip(self.gender, self.age), zip(self.weight, self.height)),