From 8ea96dd24f20dea0a1632adf491221b861ce97e9 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 7 Nov 2017 19:11:38 +0000 Subject: [PATCH] Fixes and improvements for kde operation error, dimension and range handling --- holoviews/operation/stats.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/holoviews/operation/stats.py b/holoviews/operation/stats.py index 60e84c04ba..76d9ab4ef7 100644 --- a/holoviews/operation/stats.py +++ b/holoviews/operation/stats.py @@ -85,18 +85,25 @@ def _process(self, element, key=None): if self.p.dimension: selected_dim = element.get_dimension(self.p.dimension) else: - selected_dim = [d.name for d in element.vdims + element.kdims][0] + dimensions = element.vdims+element.kdims + if not dimensions: + raise ValueError("%s element does not declare any dimensions " + "to compute the kernel density estimate on." % + type(element).__name__) + selected_dim = dimensions[0] vdim_name = '{}_density'.format(selected_dim.name) vdim_label = '{} Density'.format(selected_dim.label) - vdims = [Dimension(vdim_nam, label=vdim_label)] + vdims = [Dimension(vdim_name, label=vdim_label)] data = element.dimension_values(selected_dim) bin_range = self.p.bin_range or element.range(selected_dim) if bin_range == (0, 0) or any(not np.isfinite(r) for r in bin_range): bin_range = (0, 1) + elif bin_range[0] == bin_range[1]: + bin_range = (bin_range[0]-0.5, bin_range[1]+0.5) data = data[np.isfinite(data)] - if len(data): + if len(data) > 1: kde = stats.gaussian_kde(data) if self.p.bandwidth: kde.set_bandwidth(self.p.bandwidth) @@ -159,6 +166,9 @@ def _process(self, element, key=None): except ImportError: raise ImportError('%s operation requires SciPy to be installed.' % type(self).__name__) + if len(element.dimensions()) < 2: + raise ValueError("bivariate_kde can only be computed on elements " + "declaring at least two dimensions.") xdim, ydim = element.dimensions()[:2] params = {} if isinstance(element, Bivariate): @@ -174,8 +184,13 @@ def _process(self, element, key=None): ymin, ymax = self.p.y_range or element.range(1) if any(not np.isfinite(v) for v in (xmin, xmax)): xmin, xmax = -0.5, 0.5 + elif xmin == xmax: + xmin, xmax = xmin-0.5, xmax+0.5 if any(not np.isfinite(v) for v in (ymin, ymax)): ymin, ymax = -0.5, 0.5 + elif ymin == ymax: + ymin, ymax = ymin-0.5, ymax+0.5 + if len(element) > 1: kde = stats.gaussian_kde(data) if self.p.bandwidth: