Repository: pandas-dev/pandas

Issue:
BUG? Can construct constant Series and DataFrame, but not Panel or Panel4D
Is it accidental that the Series and DataFrame constructors accept a single number for `data`, but the Panel and Panel4D constructors do not?

```
In [182]: from pandas import Series, DataFrame, Panel, Panel4D

In [183]: Series(1., index=range(2))
Out[183]:
0    1
1    1
dtype: float64

In [184]: DataFrame(1., index=range(2), columns=range(2))
Out[184]:
   0  1
0  1  1
1  1  1

In [185]: Panel(1., items=range(2), major_axis=range(2), minor_axis=range(2))
---------------------------------------------------------------------------
PandasError                               Traceback (most recent call last)
<ipython-input-185-89f6618b848f> in <module>()
----> 1 Panel(1., items=range(2), major_axis=range(2), minor_axis=range(2))

C:\Python34\lib\site-packages\pandas\core\panel.py in __init__(self, data, items, major_axis, minor_axis, copy, dtype)
    133                  copy=False, dtype=None):
    134         self._init_data(data=data, items=items, major_axis=major_axis,
--> 135                         minor_axis=minor_axis, copy=copy, dtype=dtype)
    136
    137     def _init_data(self, data, copy, dtype, **kwargs):

C:\Python34\lib\site-packages\pandas\core\panel.py in _init_data(self, data, copy, dtype, **kwargs)
    161             dtype = None
    162         else:  # pragma: no cover
--> 163             raise PandasError('Panel constructor not properly called!')
    164
    165         NDFrame.__init__(self, mgr, axes=axes, copy=copy, dtype=dtype)

PandasError: Panel constructor not properly called!

In [186]: Panel4D(1., labels=range(2), items=range(2), major_axis=range(2), minor_axis=range(2))
---------------------------------------------------------------------------
PandasError                               Traceback (most recent call last)
<ipython-input-187-8f22d9107a3e> in <module>()
----> 1 Panel4D(1., labels=range(2), items=range(2), major_axis=range(2), minor_axis=range(2))

C:\Python34\lib\site-packages\pandas\core\panel4d.py in panel4d_init(self, data, labels, items, major_axis, minor_axis, copy, dtype)
     37     self._init_data(data=data, labels=labels, items=items,
     38                     major_axis=major_axis, minor_axis=minor_axis,
---> 39                     copy=copy, dtype=dtype)
     40
     41 Panel4D.__init__ = panel4d_init

C:\Python34\lib\site-packages\pandas\core\panel.py in _init_data(self, data, copy, dtype, **kwargs)
    161             dtype = None
    162         else:  # pragma: no cover
--> 163             raise PandasError('Panel constructor not properly called!')
    164
    165         NDFrame.__init__(self, mgr, axes=axes, copy=copy, dtype=dtype)

PandasError: Panel constructor not properly called!
```



Discussion:
Panel and subclasses use the same constructors (so a panel and Panel4d should behave similarly)

but this should work with a scalar 


Resolving patch:
diff --git a/pandas/core/panel.py b/pandas/core/panel.py
--- a/pandas/core/panel.py
+++ b/pandas/core/panel.py
@@ -165,6 +165,13 @@ def _init_data(self, data, copy, dtype, **kwargs):
             mgr = self._init_matrix(data, passed_axes, dtype=dtype, copy=copy)
             copy = False
             dtype = None
+        elif lib.isscalar(data) and all(x is not None for x in passed_axes):
+            if dtype is None:
+                dtype, data = _infer_dtype_from_scalar(data)
+            values = np.empty([len(x) for x in passed_axes], dtype=dtype)
+            values.fill(data)
+            mgr = self._init_matrix(values, passed_axes, dtype=dtype, copy=False)
+            copy = False
         else:  # pragma: no cover
             raise PandasError('Panel constructor not properly called!')
 


Test patch:
diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py
--- a/pandas/tests/test_panel.py
+++ b/pandas/tests/test_panel.py
@@ -888,6 +888,21 @@ def test_constructor(self):
         wp = Panel(vals, copy=True)
         self.assertIsNot(wp.values, vals)
 
+        # GH #8285, test when scalar data is used to construct a Panel
+        # if dtype is not passed, it should be inferred
+        value_and_dtype = [(1, int), (3.14, float), ('foo', np.object_)]
+        for (val, dtype) in value_and_dtype:
+            wp = Panel(val, items=range(2), major_axis=range(3), minor_axis=range(4))
+            vals = np.empty((2, 3, 4), dtype=dtype)
+            vals.fill(val)
+            assert_panel_equal(wp, Panel(vals, dtype=dtype))
+
+        # test the case when dtype is passed
+        wp = Panel(1, items=range(2), major_axis=range(3), minor_axis=range(4), dtype=float)
+        vals = np.empty((2, 3, 4), dtype=float)
+        vals.fill(1)
+        assert_panel_equal(wp, Panel(vals, dtype=float))
+
     def test_constructor_cast(self):
         zero_filled = self.panel.fillna(0)
 
diff --git a/pandas/tests/test_panel4d.py b/pandas/tests/test_panel4d.py
--- a/pandas/tests/test_panel4d.py
+++ b/pandas/tests/test_panel4d.py
@@ -629,6 +629,21 @@ def test_constructor(self):
         panel4d = Panel4D(vals, copy=True)
         self.assertIsNot(panel4d.values, vals)
 
+        # GH #8285, test when scalar data is used to construct a Panel4D
+        # if dtype is not passed, it should be inferred
+        value_and_dtype = [(1, int), (3.14, float), ('foo', np.object_)]
+        for (val, dtype) in value_and_dtype:
+            panel4d = Panel4D(val, labels=range(2), items=range(3), major_axis=range(4), minor_axis=range(5))
+            vals = np.empty((2, 3, 4, 5), dtype=dtype)
+            vals.fill(val)
+            assert_panel4d_equal(panel4d, Panel4D(vals, dtype=dtype))
+
+        # test the case when dtype is passed
+        panel4d = Panel4D(1, labels=range(2), items=range(3), major_axis=range(4), minor_axis=range(5), dtype=float)
+        vals = np.empty((2, 3, 4, 5), dtype=float)
+        vals.fill(1)
+        assert_panel4d_equal(panel4d, Panel4D(vals, dtype=float))
+
     def test_constructor_cast(self):
         zero_filled = self.panel4d.fillna(0)