Repository: pandas-dev/pandas

Issue:
BUG: fully reindexing panel is incorrect when missing items
Fully reindexing a panel copies sub-frames when missing top-level items

IOW, this should have a `nan` frame for 'Item2'

```
In [1]: df = DataFrame(np.random.randn(4,3))
 [4]: p = Panel({ 'Item1' : df })

In [12]: p['Item2'] = np.nan

In [13]: p
Out[13]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 4 (major_axis) x 3 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 0 to 3
Minor_axis axis: 0 to 2

In [5]:  items = ['Item1','Item2']

In [8]: major_axis = np.arange(4)

In [9]: minor_axis = np.arange(3)

In [10]: result = p.reindex(items=items,major_axis=major_axis,minor_axis=minor_axis)

In [11]: result.ix['Item2']
Out[11]: 
          0         1         2
0  1.420715  0.972559 -1.334794
1 -0.165063 -1.811950 -1.107652
2 -1.412676  0.376777 -0.521125
3  2.119229  1.221648 -1.078299

[4 rows x 3 columns]

In [14]: p['Item2']
Out[14]: 
    0   1   2
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN

[4 rows x 3 columns]
```



Discussion:

Resolving patch:
diff --git a/pandas/core/panel.py b/pandas/core/panel.py
--- a/pandas/core/panel.py
+++ b/pandas/core/panel.py
@@ -585,41 +585,8 @@ def tail(self, n=5):
         raise NotImplementedError
 
     def _needs_reindex_multi(self, axes, method, level):
-        # only allowing multi-index on Panel (and not > dims)
-        return (method is None and
-                not self._is_mixed_type and
-                self._AXIS_LEN <= 3 and
-                com._count_not_none(*axes.values()) == 3)
-
-    def _reindex_multi(self, axes, copy, fill_value):
-        """ we are guaranteed non-Nones in the axes! """
-        items = axes['items']
-        major = axes['major_axis']
-        minor = axes['minor_axis']
-        a0, a1, a2 = len(items), len(major), len(minor)
-
-        values = self.values
-        new_values = np.empty((a0, a1, a2), dtype=values.dtype)
-
-        new_items, indexer0 = self.items.reindex(items)
-        new_major, indexer1 = self.major_axis.reindex(major)
-        new_minor, indexer2 = self.minor_axis.reindex(minor)
-
-        if indexer0 is None:
-            indexer0 = lrange(len(new_items))
-
-        if indexer1 is None:
-            indexer1 = lrange(len(new_major))
-
-        if indexer2 is None:
-            indexer2 = lrange(len(new_minor))
-
-        for i, ind in enumerate(indexer0):
-            com.take_2d_multi(values[ind], (indexer1, indexer2),
-                              out=new_values[i])
-
-        return Panel(new_values, items=new_items, major_axis=new_major,
-                     minor_axis=new_minor)
+        """ don't allow a multi reindex on Panel or above ndim """
+        return False
 
     def dropna(self, axis=0, how='any', inplace=False, **kwargs):
         """


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
@@ -1082,14 +1082,6 @@ def test_reindex(self):
         result = self.panel.reindex(minor=new_minor)
         assert_frame_equal(result['ItemB'], ref.reindex(columns=new_minor))
 
-        result = self.panel.reindex(items=self.panel.items,
-                                    major=self.panel.major_axis,
-                                    minor=self.panel.minor_axis)
-
-        self.assert_(result.items is self.panel.items)
-        self.assert_(result.major_axis is self.panel.major_axis)
-        self.assert_(result.minor_axis is self.panel.minor_axis)
-
         # this ok
         result = self.panel.reindex()
         assert_panel_equal(result,self.panel)
@@ -1110,6 +1102,46 @@ def test_reindex(self):
         assert_panel_equal(result,self.panel)
         self.assert_((result is self.panel) == True)
 
+    def test_reindex_multi(self):
+
+        # with and without copy full reindexing
+        result = self.panel.reindex(items=self.panel.items,
+                                    major=self.panel.major_axis,
+                                    minor=self.panel.minor_axis,
+                                    copy = False)
+
+        self.assert_(result.items is self.panel.items)
+        self.assert_(result.major_axis is self.panel.major_axis)
+        self.assert_(result.minor_axis is self.panel.minor_axis)
+
+        result = self.panel.reindex(items=self.panel.items,
+                                    major=self.panel.major_axis,
+                                    minor=self.panel.minor_axis,
+                                    copy = False)
+        assert_panel_equal(result,self.panel)
+
+        # multi-axis indexing consistency
+        # GH 5900
+        df = DataFrame(np.random.randn(4,3))
+        p = Panel({ 'Item1' : df })
+        expected = Panel({ 'Item1' : df })
+        expected['Item2'] = np.nan
+
+        items = ['Item1','Item2']
+        major_axis = np.arange(4)
+        minor_axis = np.arange(3)
+
+        results = []
+        results.append(p.reindex(items=items, major_axis=major_axis, copy=True))
+        results.append(p.reindex(items=items, major_axis=major_axis, copy=False))
+        results.append(p.reindex(items=items, minor_axis=minor_axis, copy=True))
+        results.append(p.reindex(items=items, minor_axis=minor_axis, copy=False))
+        results.append(p.reindex(items=items, major_axis=major_axis, minor_axis=minor_axis, copy=True))
+        results.append(p.reindex(items=items, major_axis=major_axis, minor_axis=minor_axis, copy=False))
+
+        for i, r in enumerate(results):
+            assert_panel_equal(expected,r)
+
     def test_reindex_like(self):
         # reindex_like
         smaller = self.panel.reindex(items=self.panel.items[:-1],