We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Empty Box-Whisker plot with the Matplotlib backend when vdims has NaNs
The following snippet correctly returns a Box-Whisker plot grouped by *carrier* with the Bokeh backend but just returns an empty plot with the matplotlib backend.

```python
import holoviews as hv
from hvplot.sample_data import us_crime, airline_flights

flights = airline_flights.to_dask().persist()
flight_subset = flights[flights.carrier.isin(['AA', 'US', 'OH'])]

ds = hv.Dataset(flight_subset, kdims=['carrier'], vdims=['depdelay'])
hv.BoxWhisker(ds)
```
![image](https://user-images.githubusercontent.com/35924738/140918683-7caaf7e2-e1cc-4d75-bde3-b3c56863025e.png)

Note that this has nothing to do with Dask, since adding `flight_subset = flight_subset.compute()` has no effect.

I've done some exploration and found out that the `depdelay` column has `NaN`s values, replacing them with `0` (or any float) fixes the issue. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `holoviews/plotting/mpl/stats.py`
Content:
```
1 import param
2 import numpy as np
3 
4 from ...core.ndmapping import sorted_context
5 from .chart import AreaPlot, ChartPlot
6 from .path import PolygonPlot
7 from .plot import AdjoinedPlot
8 
9 
10 class DistributionPlot(AreaPlot):
11     """
12     DistributionPlot visualizes a distribution of values as a KDE.
13     """
14 
15     bandwidth = param.Number(default=None, doc="""
16         The bandwidth of the kernel for the density estimate.""")
17 
18     cut = param.Number(default=3, doc="""
19         Draw the estimate to cut * bw from the extreme data points.""")
20 
21     filled = param.Boolean(default=True, doc="""
22         Whether the bivariate contours should be filled.""")
23 
24 
25 class BivariatePlot(PolygonPlot):
26     """
27     Bivariate plot visualizes two-dimensional kernel density
28     estimates. Additionally, by enabling the joint option, the
29     marginals distributions can be plotted alongside each axis (does
30     not animate or compose).
31     """
32 
33     bandwidth = param.Number(default=None, doc="""
34         The bandwidth of the kernel for the density estimate.""")
35 
36     cut = param.Number(default=3, doc="""
37         Draw the estimate to cut * bw from the extreme data points.""")
38 
39     filled = param.Boolean(default=False, doc="""
40         Whether the bivariate contours should be filled.""")
41 
42     levels = param.ClassSelector(default=10, class_=(list, int), doc="""
43         A list of scalar values used to specify the contour levels.""")
44 
45 
46 class BoxPlot(ChartPlot):
47     """
48     BoxPlot plots the ErrorBar Element type and supporting
49     both horizontal and vertical error bars via the 'horizontal'
50     plot option.
51     """
52 
53     style_opts = ['notch', 'sym', 'whis', 'bootstrap',
54                   'conf_intervals', 'widths', 'showmeans',
55                   'show_caps', 'showfliers', 'boxprops',
56                   'whiskerprops', 'capprops', 'flierprops',
57                   'medianprops', 'meanprops', 'meanline']
58 
59     _nonvectorized_styles = style_opts
60 
61     _plot_methods = dict(single='boxplot')
62 
63     def get_extents(self, element, ranges, range_type='combined'):
64         return super().get_extents(
65             element, ranges, range_type, 'categorical', element.vdims[0]
66         )
67 
68     def get_data(self, element, ranges, style):
69         if element.kdims:
70             with sorted_context(False):
71                 groups = element.groupby(element.kdims).data.items()
72         else:
73             groups = [(element.label, element)]
74 
75         data, labels = [], []
76         for key, group in groups:
77             if element.kdims:
78                 label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])
79             else:
80                 label = key
81             data.append(group[group.vdims[0]])
82             labels.append(label)
83         style['labels'] = labels
84         style = {k: v for k, v in style.items()
85                  if k not in ['zorder', 'label']}
86         style['vert'] = not self.invert_axes
87         format_kdims = [kd.clone(value_format=None) for kd in element.kdims]
88         return (data,), style, {'dimensions': [format_kdims, element.vdims[0]]}
89 
90     def init_artists(self, ax, plot_args, plot_kwargs):
91         artists = ax.boxplot(*plot_args, **plot_kwargs)
92         artists['artist'] = artists['boxes']
93         return artists
94 
95     def teardown_handles(self):
96         for g in ('whiskers', 'fliers', 'medians', 'boxes', 'caps', 'means'):
97             for v in self.handles.get(g, []):
98                 v.remove()
99 
100 
101 class SideBoxPlot(AdjoinedPlot, BoxPlot):
102 
103     bgcolor = param.Parameter(default=(1, 1, 1, 0), doc="""
104         Make plot background invisible.""")
105 
106     border_size = param.Number(default=0, doc="""
107         The size of the border expressed as a fraction of the main plot.""")
108 
109     xaxis = param.ObjectSelector(default='bare',
110                                  objects=['top', 'bottom', 'bare', 'top-bare',
111                                           'bottom-bare', None], doc="""
112         Whether and where to display the xaxis, bare options allow suppressing
113         all axis labels including ticks and xlabel. Valid options are 'top',
114         'bottom', 'bare', 'top-bare' and 'bottom-bare'.""")
115 
116     yaxis = param.ObjectSelector(default='bare',
117                                  objects=['left', 'right', 'bare', 'left-bare',
118                                           'right-bare', None], doc="""
119         Whether and where to display the yaxis, bare options allow suppressing
120         all axis labels including ticks and ylabel. Valid options are 'left',
121         'right', 'bare' 'left-bare' and 'right-bare'.""")
122 
123     def __init__(self, *args, **kwargs):
124         super().__init__(*args, **kwargs)
125         if self.adjoined:
126             self.invert_axes = not self.invert_axes
127 
128 
129 class ViolinPlot(BoxPlot):
130     """
131     BoxPlot plots the ErrorBar Element type and supporting
132     both horizontal and vertical error bars via the 'horizontal'
133     plot option.
134     """
135 
136     bandwidth = param.Number(default=None, doc="""
137         Allows supplying explicit bandwidth value rather than relying
138         on scott or silverman method.""")
139 
140     inner = param.ObjectSelector(objects=['box', 'medians', None],
141                                  default='box', doc="""
142         Inner visual indicator for distribution values:
143 
144           * box - A small box plot
145           * stick - Lines indicating each sample value
146           * quartiles - Indicates first, second and third quartiles
147         """)
148 
149     _plot_methods = dict(single='violinplot')
150 
151     style_opts = ['showmeans', 'facecolors', 'showextrema', 'bw_method',
152                   'widths', 'stats_color', 'box_color', 'alpha', 'edgecolors']
153 
154     _nonvectorized_styles = [
155         s for s in style_opts if s not in ('facecolors', 'edgecolors', 'widths')
156     ]
157 
158     def init_artists(self, ax, plot_args, plot_kwargs):
159         box_color = plot_kwargs.pop('box_color', 'black')
160         stats_color = plot_kwargs.pop('stats_color', 'black')
161         facecolors = plot_kwargs.pop('facecolors', [])
162         edgecolors = plot_kwargs.pop('edgecolors', 'black')
163         labels = plot_kwargs.pop('labels')
164         alpha = plot_kwargs.pop('alpha', 1.)
165         showmedians = self.inner == 'medians'
166         bw_method = self.bandwidth or 'scott'
167         artists = ax.violinplot(*plot_args, bw_method=bw_method,
168                                showmedians=showmedians, **plot_kwargs)
169         if self.inner == 'box':
170             box = ax.boxplot(*plot_args, positions=plot_kwargs['positions'],
171                              showfliers=False, showcaps=False, patch_artist=True,
172                              boxprops={'facecolor': box_color},
173                              medianprops={'color': 'white'}, widths=0.1,
174                              labels=labels)
175             artists.update(box)
176         for body, color in zip(artists['bodies'], facecolors):
177             body.set_facecolors(color)
178             body.set_edgecolors(edgecolors)
179             body.set_alpha(alpha)
180         for stat in ['cmedians', 'cmeans', 'cmaxes', 'cmins', 'cbars']:
181             if stat in artists:
182                 artists[stat].set_edgecolors(stats_color)
183         artists['bodies'] = artists['bodies']
184         return artists
185 
186     def get_data(self, element, ranges, style):
187         if element.kdims:
188             with sorted_context(False):
189                 groups = element.groupby(element.kdims).data.items()
190         else:
191             groups = [(element.label, element)]
192 
193         data, labels, colors = [], [], []
194         elstyle = self.lookup_options(element, 'style')
195         for i, (key, group) in enumerate(groups):
196             if element.kdims:
197                 label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])
198             else:
199                 label = key
200             d = group[group.vdims[0]]
201             data.append(d[np.isfinite(d)])
202             labels.append(label)
203             colors.append(elstyle[i].get('facecolors', 'blue'))
204         style['positions'] = list(range(len(data)))
205         style['labels'] = labels
206         style['facecolors'] = colors
207 
208         if element.ndims > 0:
209             element = element.aggregate(function=np.mean)
210         else:
211             element = element.clone([(element.aggregate(function=np.mean),)])
212 
213         new_style = self._apply_transforms(element, ranges, style)
214         style = {k: v for k, v in new_style.items()
215                  if k not in ['zorder', 'label']}
216         style['vert'] = not self.invert_axes
217         format_kdims = [kd.clone(value_format=None) for kd in element.kdims]
218         ticks = {'yticks' if self.invert_axes else 'xticks': list(enumerate(labels))}
219         return (data,), style, dict(dimensions=[format_kdims, element.vdims[0]], **ticks)
220 
221     def teardown_handles(self):
222         box_artists = ('cmedians', 'cmeans', 'cmaxes', 'cmins', 'cbars', 'bodies')
223         violin_artists = ('whiskers', 'fliers', 'medians', 'boxes', 'caps', 'means')
224         for group in box_artists+violin_artists:
225             for v in self.handles.get(group, []):
226                 v.remove()
227
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/holoviews/plotting/mpl/stats.py b/holoviews/plotting/mpl/stats.py
--- a/holoviews/plotting/mpl/stats.py
+++ b/holoviews/plotting/mpl/stats.py
@@ -78,7 +78,8 @@
                 label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])
             else:
                 label = key
-            data.append(group[group.vdims[0]])
+            d = group[group.vdims[0]]
+            data.append(d[np.isfinite(d)])
             labels.append(label)
         style['labels'] = labels
         style = {k: v for k, v in style.items()

{"golden_diff": "diff --git a/holoviews/plotting/mpl/stats.py b/holoviews/plotting/mpl/stats.py\n--- a/holoviews/plotting/mpl/stats.py\n+++ b/holoviews/plotting/mpl/stats.py\n@@ -78,7 +78,8 @@\n                 label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])\n             else:\n                 label = key\n-            data.append(group[group.vdims[0]])\n+            d = group[group.vdims[0]]\n+            data.append(d[np.isfinite(d)])\n             labels.append(label)\n         style['labels'] = labels\n         style = {k: v for k, v in style.items()\n", "issue": "Empty Box-Whisker plot with the Matplotlib backend when vdims has NaNs\nThe following snippet correctly returns a Box-Whisker plot grouped by *carrier* with the Bokeh backend but just returns an empty plot with the matplotlib backend.\r\n\r\n```python\r\nimport holoviews as hv\r\nfrom hvplot.sample_data import us_crime, airline_flights\r\n\r\nflights = airline_flights.to_dask().persist()\r\nflight_subset = flights[flights.carrier.isin(['AA', 'US', 'OH'])]\r\n\r\nds = hv.Dataset(flight_subset, kdims=['carrier'], vdims=['depdelay'])\r\nhv.BoxWhisker(ds)\r\n```\r\n![image](https://user-images.githubusercontent.com/35924738/140918683-7caaf7e2-e1cc-4d75-bde3-b3c56863025e.png)\r\n\r\nNote that this has nothing to do with Dask, since adding `flight_subset = flight_subset.compute()` has no effect.\r\n\r\nI've done some exploration and found out that the `depdelay` column has `NaN`s values, replacing them with `0` (or any float) fixes the issue. \n", "before_files": [{"content": "import param\nimport numpy as np\n\nfrom ...core.ndmapping import sorted_context\nfrom .chart import AreaPlot, ChartPlot\nfrom .path import PolygonPlot\nfrom .plot import AdjoinedPlot\n\n\nclass DistributionPlot(AreaPlot):\n    \"\"\"\n    DistributionPlot visualizes a distribution of values as a KDE.\n    \"\"\"\n\n    bandwidth = param.Number(default=None, doc=\"\"\"\n        The bandwidth of the kernel for the density estimate.\"\"\")\n\n    cut = param.Number(default=3, doc=\"\"\"\n        Draw the estimate to cut * bw from the extreme data points.\"\"\")\n\n    filled = param.Boolean(default=True, doc=\"\"\"\n        Whether the bivariate contours should be filled.\"\"\")\n\n\nclass BivariatePlot(PolygonPlot):\n    \"\"\"\n    Bivariate plot visualizes two-dimensional kernel density\n    estimates. Additionally, by enabling the joint option, the\n    marginals distributions can be plotted alongside each axis (does\n    not animate or compose).\n    \"\"\"\n\n    bandwidth = param.Number(default=None, doc=\"\"\"\n        The bandwidth of the kernel for the density estimate.\"\"\")\n\n    cut = param.Number(default=3, doc=\"\"\"\n        Draw the estimate to cut * bw from the extreme data points.\"\"\")\n\n    filled = param.Boolean(default=False, doc=\"\"\"\n        Whether the bivariate contours should be filled.\"\"\")\n\n    levels = param.ClassSelector(default=10, class_=(list, int), doc=\"\"\"\n        A list of scalar values used to specify the contour levels.\"\"\")\n\n\nclass BoxPlot(ChartPlot):\n    \"\"\"\n    BoxPlot plots the ErrorBar Element type and supporting\n    both horizontal and vertical error bars via the 'horizontal'\n    plot option.\n    \"\"\"\n\n    style_opts = ['notch', 'sym', 'whis', 'bootstrap',\n                  'conf_intervals', 'widths', 'showmeans',\n                  'show_caps', 'showfliers', 'boxprops',\n                  'whiskerprops', 'capprops', 'flierprops',\n                  'medianprops', 'meanprops', 'meanline']\n\n    _nonvectorized_styles = style_opts\n\n    _plot_methods = dict(single='boxplot')\n\n    def get_extents(self, element, ranges, range_type='combined'):\n        return super().get_extents(\n            element, ranges, range_type, 'categorical', element.vdims[0]\n        )\n\n    def get_data(self, element, ranges, style):\n        if element.kdims:\n            with sorted_context(False):\n                groups = element.groupby(element.kdims).data.items()\n        else:\n            groups = [(element.label, element)]\n\n        data, labels = [], []\n        for key, group in groups:\n            if element.kdims:\n                label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])\n            else:\n                label = key\n            data.append(group[group.vdims[0]])\n            labels.append(label)\n        style['labels'] = labels\n        style = {k: v for k, v in style.items()\n                 if k not in ['zorder', 'label']}\n        style['vert'] = not self.invert_axes\n        format_kdims = [kd.clone(value_format=None) for kd in element.kdims]\n        return (data,), style, {'dimensions': [format_kdims, element.vdims[0]]}\n\n    def init_artists(self, ax, plot_args, plot_kwargs):\n        artists = ax.boxplot(*plot_args, **plot_kwargs)\n        artists['artist'] = artists['boxes']\n        return artists\n\n    def teardown_handles(self):\n        for g in ('whiskers', 'fliers', 'medians', 'boxes', 'caps', 'means'):\n            for v in self.handles.get(g, []):\n                v.remove()\n\n\nclass SideBoxPlot(AdjoinedPlot, BoxPlot):\n\n    bgcolor = param.Parameter(default=(1, 1, 1, 0), doc=\"\"\"\n        Make plot background invisible.\"\"\")\n\n    border_size = param.Number(default=0, doc=\"\"\"\n        The size of the border expressed as a fraction of the main plot.\"\"\")\n\n    xaxis = param.ObjectSelector(default='bare',\n                                 objects=['top', 'bottom', 'bare', 'top-bare',\n                                          'bottom-bare', None], doc=\"\"\"\n        Whether and where to display the xaxis, bare options allow suppressing\n        all axis labels including ticks and xlabel. Valid options are 'top',\n        'bottom', 'bare', 'top-bare' and 'bottom-bare'.\"\"\")\n\n    yaxis = param.ObjectSelector(default='bare',\n                                 objects=['left', 'right', 'bare', 'left-bare',\n                                          'right-bare', None], doc=\"\"\"\n        Whether and where to display the yaxis, bare options allow suppressing\n        all axis labels including ticks and ylabel. Valid options are 'left',\n        'right', 'bare' 'left-bare' and 'right-bare'.\"\"\")\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self.adjoined:\n            self.invert_axes = not self.invert_axes\n\n\nclass ViolinPlot(BoxPlot):\n    \"\"\"\n    BoxPlot plots the ErrorBar Element type and supporting\n    both horizontal and vertical error bars via the 'horizontal'\n    plot option.\n    \"\"\"\n\n    bandwidth = param.Number(default=None, doc=\"\"\"\n        Allows supplying explicit bandwidth value rather than relying\n        on scott or silverman method.\"\"\")\n\n    inner = param.ObjectSelector(objects=['box', 'medians', None],\n                                 default='box', doc=\"\"\"\n        Inner visual indicator for distribution values:\n\n          * box - A small box plot\n          * stick - Lines indicating each sample value\n          * quartiles - Indicates first, second and third quartiles\n        \"\"\")\n\n    _plot_methods = dict(single='violinplot')\n\n    style_opts = ['showmeans', 'facecolors', 'showextrema', 'bw_method',\n                  'widths', 'stats_color', 'box_color', 'alpha', 'edgecolors']\n\n    _nonvectorized_styles = [\n        s for s in style_opts if s not in ('facecolors', 'edgecolors', 'widths')\n    ]\n\n    def init_artists(self, ax, plot_args, plot_kwargs):\n        box_color = plot_kwargs.pop('box_color', 'black')\n        stats_color = plot_kwargs.pop('stats_color', 'black')\n        facecolors = plot_kwargs.pop('facecolors', [])\n        edgecolors = plot_kwargs.pop('edgecolors', 'black')\n        labels = plot_kwargs.pop('labels')\n        alpha = plot_kwargs.pop('alpha', 1.)\n        showmedians = self.inner == 'medians'\n        bw_method = self.bandwidth or 'scott'\n        artists = ax.violinplot(*plot_args, bw_method=bw_method,\n                               showmedians=showmedians, **plot_kwargs)\n        if self.inner == 'box':\n            box = ax.boxplot(*plot_args, positions=plot_kwargs['positions'],\n                             showfliers=False, showcaps=False, patch_artist=True,\n                             boxprops={'facecolor': box_color},\n                             medianprops={'color': 'white'}, widths=0.1,\n                             labels=labels)\n            artists.update(box)\n        for body, color in zip(artists['bodies'], facecolors):\n            body.set_facecolors(color)\n            body.set_edgecolors(edgecolors)\n            body.set_alpha(alpha)\n        for stat in ['cmedians', 'cmeans', 'cmaxes', 'cmins', 'cbars']:\n            if stat in artists:\n                artists[stat].set_edgecolors(stats_color)\n        artists['bodies'] = artists['bodies']\n        return artists\n\n    def get_data(self, element, ranges, style):\n        if element.kdims:\n            with sorted_context(False):\n                groups = element.groupby(element.kdims).data.items()\n        else:\n            groups = [(element.label, element)]\n\n        data, labels, colors = [], [], []\n        elstyle = self.lookup_options(element, 'style')\n        for i, (key, group) in enumerate(groups):\n            if element.kdims:\n                label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])\n            else:\n                label = key\n            d = group[group.vdims[0]]\n            data.append(d[np.isfinite(d)])\n            labels.append(label)\n            colors.append(elstyle[i].get('facecolors', 'blue'))\n        style['positions'] = list(range(len(data)))\n        style['labels'] = labels\n        style['facecolors'] = colors\n\n        if element.ndims > 0:\n            element = element.aggregate(function=np.mean)\n        else:\n            element = element.clone([(element.aggregate(function=np.mean),)])\n\n        new_style = self._apply_transforms(element, ranges, style)\n        style = {k: v for k, v in new_style.items()\n                 if k not in ['zorder', 'label']}\n        style['vert'] = not self.invert_axes\n        format_kdims = [kd.clone(value_format=None) for kd in element.kdims]\n        ticks = {'yticks' if self.invert_axes else 'xticks': list(enumerate(labels))}\n        return (data,), style, dict(dimensions=[format_kdims, element.vdims[0]], **ticks)\n\n    def teardown_handles(self):\n        box_artists = ('cmedians', 'cmeans', 'cmaxes', 'cmins', 'cbars', 'bodies')\n        violin_artists = ('whiskers', 'fliers', 'medians', 'boxes', 'caps', 'means')\n        for group in box_artists+violin_artists:\n            for v in self.handles.get(group, []):\n                v.remove()\n", "path": "holoviews/plotting/mpl/stats.py"}], "after_files": [{"content": "import param\nimport numpy as np\n\nfrom ...core.ndmapping import sorted_context\nfrom .chart import AreaPlot, ChartPlot\nfrom .path import PolygonPlot\nfrom .plot import AdjoinedPlot\n\n\nclass DistributionPlot(AreaPlot):\n    \"\"\"\n    DistributionPlot visualizes a distribution of values as a KDE.\n    \"\"\"\n\n    bandwidth = param.Number(default=None, doc=\"\"\"\n        The bandwidth of the kernel for the density estimate.\"\"\")\n\n    cut = param.Number(default=3, doc=\"\"\"\n        Draw the estimate to cut * bw from the extreme data points.\"\"\")\n\n    filled = param.Boolean(default=True, doc=\"\"\"\n        Whether the bivariate contours should be filled.\"\"\")\n\n\nclass BivariatePlot(PolygonPlot):\n    \"\"\"\n    Bivariate plot visualizes two-dimensional kernel density\n    estimates. Additionally, by enabling the joint option, the\n    marginals distributions can be plotted alongside each axis (does\n    not animate or compose).\n    \"\"\"\n\n    bandwidth = param.Number(default=None, doc=\"\"\"\n        The bandwidth of the kernel for the density estimate.\"\"\")\n\n    cut = param.Number(default=3, doc=\"\"\"\n        Draw the estimate to cut * bw from the extreme data points.\"\"\")\n\n    filled = param.Boolean(default=False, doc=\"\"\"\n        Whether the bivariate contours should be filled.\"\"\")\n\n    levels = param.ClassSelector(default=10, class_=(list, int), doc=\"\"\"\n        A list of scalar values used to specify the contour levels.\"\"\")\n\n\nclass BoxPlot(ChartPlot):\n    \"\"\"\n    BoxPlot plots the ErrorBar Element type and supporting\n    both horizontal and vertical error bars via the 'horizontal'\n    plot option.\n    \"\"\"\n\n    style_opts = ['notch', 'sym', 'whis', 'bootstrap',\n                  'conf_intervals', 'widths', 'showmeans',\n                  'show_caps', 'showfliers', 'boxprops',\n                  'whiskerprops', 'capprops', 'flierprops',\n                  'medianprops', 'meanprops', 'meanline']\n\n    _nonvectorized_styles = style_opts\n\n    _plot_methods = dict(single='boxplot')\n\n    def get_extents(self, element, ranges, range_type='combined'):\n        return super().get_extents(\n            element, ranges, range_type, 'categorical', element.vdims[0]\n        )\n\n    def get_data(self, element, ranges, style):\n        if element.kdims:\n            with sorted_context(False):\n                groups = element.groupby(element.kdims).data.items()\n        else:\n            groups = [(element.label, element)]\n\n        data, labels = [], []\n        for key, group in groups:\n            if element.kdims:\n                label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])\n            else:\n                label = key\n            d = group[group.vdims[0]]\n            data.append(d[np.isfinite(d)])\n            labels.append(label)\n        style['labels'] = labels\n        style = {k: v for k, v in style.items()\n                 if k not in ['zorder', 'label']}\n        style['vert'] = not self.invert_axes\n        format_kdims = [kd.clone(value_format=None) for kd in element.kdims]\n        return (data,), style, {'dimensions': [format_kdims, element.vdims[0]]}\n\n    def init_artists(self, ax, plot_args, plot_kwargs):\n        artists = ax.boxplot(*plot_args, **plot_kwargs)\n        artists['artist'] = artists['boxes']\n        return artists\n\n    def teardown_handles(self):\n        for g in ('whiskers', 'fliers', 'medians', 'boxes', 'caps', 'means'):\n            for v in self.handles.get(g, []):\n                v.remove()\n\n\nclass SideBoxPlot(AdjoinedPlot, BoxPlot):\n\n    bgcolor = param.Parameter(default=(1, 1, 1, 0), doc=\"\"\"\n        Make plot background invisible.\"\"\")\n\n    border_size = param.Number(default=0, doc=\"\"\"\n        The size of the border expressed as a fraction of the main plot.\"\"\")\n\n    xaxis = param.ObjectSelector(default='bare',\n                                 objects=['top', 'bottom', 'bare', 'top-bare',\n                                          'bottom-bare', None], doc=\"\"\"\n        Whether and where to display the xaxis, bare options allow suppressing\n        all axis labels including ticks and xlabel. Valid options are 'top',\n        'bottom', 'bare', 'top-bare' and 'bottom-bare'.\"\"\")\n\n    yaxis = param.ObjectSelector(default='bare',\n                                 objects=['left', 'right', 'bare', 'left-bare',\n                                          'right-bare', None], doc=\"\"\"\n        Whether and where to display the yaxis, bare options allow suppressing\n        all axis labels including ticks and ylabel. Valid options are 'left',\n        'right', 'bare' 'left-bare' and 'right-bare'.\"\"\")\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self.adjoined:\n            self.invert_axes = not self.invert_axes\n\n\nclass ViolinPlot(BoxPlot):\n    \"\"\"\n    BoxPlot plots the ErrorBar Element type and supporting\n    both horizontal and vertical error bars via the 'horizontal'\n    plot option.\n    \"\"\"\n\n    bandwidth = param.Number(default=None, doc=\"\"\"\n        Allows supplying explicit bandwidth value rather than relying\n        on scott or silverman method.\"\"\")\n\n    inner = param.ObjectSelector(objects=['box', 'medians', None],\n                                 default='box', doc=\"\"\"\n        Inner visual indicator for distribution values:\n\n          * box - A small box plot\n          * stick - Lines indicating each sample value\n          * quartiles - Indicates first, second and third quartiles\n        \"\"\")\n\n    _plot_methods = dict(single='violinplot')\n\n    style_opts = ['showmeans', 'facecolors', 'showextrema', 'bw_method',\n                  'widths', 'stats_color', 'box_color', 'alpha', 'edgecolors']\n\n    _nonvectorized_styles = [\n        s for s in style_opts if s not in ('facecolors', 'edgecolors', 'widths')\n    ]\n\n    def init_artists(self, ax, plot_args, plot_kwargs):\n        box_color = plot_kwargs.pop('box_color', 'black')\n        stats_color = plot_kwargs.pop('stats_color', 'black')\n        facecolors = plot_kwargs.pop('facecolors', [])\n        edgecolors = plot_kwargs.pop('edgecolors', 'black')\n        labels = plot_kwargs.pop('labels')\n        alpha = plot_kwargs.pop('alpha', 1.)\n        showmedians = self.inner == 'medians'\n        bw_method = self.bandwidth or 'scott'\n        artists = ax.violinplot(*plot_args, bw_method=bw_method,\n                               showmedians=showmedians, **plot_kwargs)\n        if self.inner == 'box':\n            box = ax.boxplot(*plot_args, positions=plot_kwargs['positions'],\n                             showfliers=False, showcaps=False, patch_artist=True,\n                             boxprops={'facecolor': box_color},\n                             medianprops={'color': 'white'}, widths=0.1,\n                             labels=labels)\n            artists.update(box)\n        for body, color in zip(artists['bodies'], facecolors):\n            body.set_facecolors(color)\n            body.set_edgecolors(edgecolors)\n            body.set_alpha(alpha)\n        for stat in ['cmedians', 'cmeans', 'cmaxes', 'cmins', 'cbars']:\n            if stat in artists:\n                artists[stat].set_edgecolors(stats_color)\n        artists['bodies'] = artists['bodies']\n        return artists\n\n    def get_data(self, element, ranges, style):\n        if element.kdims:\n            with sorted_context(False):\n                groups = element.groupby(element.kdims).data.items()\n        else:\n            groups = [(element.label, element)]\n\n        data, labels, colors = [], [], []\n        elstyle = self.lookup_options(element, 'style')\n        for i, (key, group) in enumerate(groups):\n            if element.kdims:\n                label = ','.join([d.pprint_value(v) for d, v in zip(element.kdims, key)])\n            else:\n                label = key\n            d = group[group.vdims[0]]\n            data.append(d[np.isfinite(d)])\n            labels.append(label)\n            colors.append(elstyle[i].get('facecolors', 'blue'))\n        style['positions'] = list(range(len(data)))\n        style['labels'] = labels\n        style['facecolors'] = colors\n\n        if element.ndims > 0:\n            element = element.aggregate(function=np.mean)\n        else:\n            element = element.clone([(element.aggregate(function=np.mean),)])\n\n        new_style = self._apply_transforms(element, ranges, style)\n        style = {k: v for k, v in new_style.items()\n                 if k not in ['zorder', 'label']}\n        style['vert'] = not self.invert_axes\n        format_kdims = [kd.clone(value_format=None) for kd in element.kdims]\n        ticks = {'yticks' if self.invert_axes else 'xticks': list(enumerate(labels))}\n        return (data,), style, dict(dimensions=[format_kdims, element.vdims[0]], **ticks)\n\n    def teardown_handles(self):\n        box_artists = ('cmedians', 'cmeans', 'cmaxes', 'cmins', 'cbars', 'bodies')\n        violin_artists = ('whiskers', 'fliers', 'medians', 'boxes', 'caps', 'means')\n        for group in box_artists+violin_artists:\n            for v in self.handles.get(group, []):\n                v.remove()\n", "path": "holoviews/plotting/mpl/stats.py"}]}