Repository: holoviz/holoviews

Issue:
Cannot plot unnamed pd.Series
#### ALL software version info
holoviews: 1.14.4
jupyterlab: 2.3.1
bokeh: 2.3.2

#### Description of expected behavior and the observed behavior

Plotting pandas Series with `name` attribute set to None raises an exception.

#### Complete, minimal, self-contained example code that reproduces the issue

```
import pandas as pd

series = pd.Series([1,2])
print(series.name)
# Raises exception
hv.Curve(series)

# Works because accessing df['a'] returns a series with name == 'a'
df = pd.DataFrame(dict(a=series))
hv.Curve(df['a'])

# Works as well
series2 = pd.Series([1,2])
series2.name = 'foo'
hv.Curve(series2)

# Fails with:
# ValueError: Dimension name cannot be the empty string
series3 = pd.Series([1,2])
series3.name = ''
hv.Curve(series3)
```

#### Stack traceback and/or browser JavaScript console output

```
---------------------------------------------------------------------------
DataError                                 Traceback (most recent call last)
<ipython-input-29-41d62e9ba886> in <module>
      3 series = pd.Series([1,2])
      4 print(series.name)
----> 5 hv.Curve(series)

venv-3.9/lib/python3.9/site-packages/holoviews/element/selection.py in __init__(self, *args, **kwargs)
     19 
     20     def __init__(self, *args, **kwargs):
---> 21         super(SelectionIndexExpr, self).__init__(*args, **kwargs)
     22         self._index_skip = False
     23 

venv-3.9/lib/python3.9/site-packages/holoviews/element/chart.py in __init__(self, data, kdims, vdims, **params)
     50         if len(params.get('kdims', [])) == self._max_kdim_count + 1:
     51             self.param.warning('Chart elements should only be supplied a single kdim')
---> 52         super(Chart, self).__init__(data, **params)
     53 
     54     def __getitem__(self, index):

venv-3.9/lib/python3.9/site-packages/holoviews/core/data/__init__.py in __init__(self, data, kdims, vdims, **kwargs)
    339 
    340         validate_vdims = kwargs.pop('_validate_vdims', True)
--> 341         initialized = Interface.initialize(type(self), data, kdims, vdims,
    342                                            datatype=kwargs.get('datatype'))
    343         (data, self.interface, dims, extra_kws) = initialized

venv-3.9/lib/python3.9/site-packages/holoviews/core/data/interface.py in initialize(cls, eltype, data, kdims, vdims, datatype)
    254                 continue
    255             try:
--> 256                 (data, dims, extra_kws) = interface.init(eltype, data, kdims, vdims)
    257                 break
    258             except DataError:

venv-3.9/lib/python3.9/site-packages/holoviews/core/data/pandas.py in init(cls, eltype, data, kdims, vdims)
     72                     break
     73             if any(isinstance(d, (np.int64, int)) for d in kdims+vdims):
---> 74                 raise DataError("pandas DataFrame column names used as dimensions "
     75                                 "must be strings not integers.", cls)
     76 

DataError: pandas DataFrame column names used as dimensions must be strings not integers.

PandasInterface expects tabular data, for more information on supported datatypes see http://holoviews.org/user_guide/Tabular_Datasets.html
```



Discussion:

Resolving patch:
diff --git a/holoviews/core/data/pandas.py b/holoviews/core/data/pandas.py
--- a/holoviews/core/data/pandas.py
+++ b/holoviews/core/data/pandas.py
@@ -33,7 +33,8 @@ def init(cls, eltype, data, kdims, vdims):
         kdim_param = element_params['kdims']
         vdim_param = element_params['vdims']
         if util.is_series(data):
-            data = data.to_frame()
+            name = data.name or util.anonymous_dimension_label
+            data = data.to_frame(name=name)
         if util.is_dataframe(data):
             ncols = len(data.columns)
             index_names = data.index.names if isinstance(data, pd.DataFrame) else [data.index.name]
diff --git a/holoviews/core/util.py b/holoviews/core/util.py
--- a/holoviews/core/util.py
+++ b/holoviews/core/util.py
@@ -36,6 +36,8 @@
 arraylike_types = (np.ndarray,)
 masked_types = ()
 
+anonymous_dimension_label = '_'
+
 try:
     import pandas as pd
 except ImportError:


Test patch: