Repository: pandas-dev/pandas

Issue:
MultiIndex on complex DataFrame.apply
Seem to be converting MultiIndex into tuples when I do a complex apply:

```
import pandas as pd

s = pd.DataFrame([[1,2], [3,4], [5,6]])
s.index = pd.MultiIndex.from_arrays([['a','a','b'], ['c','d','d']])
s.columns = ['col1','col2']
s
```

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th></th>
      <th>col1</th>
      <th>col2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td rowspan="2" valign="top"><strong>a</strong></td>
      <td><strong>c</strong></td>
      <td> 1</td>
      <td> 2</td>
    </tr>
    <tr>
      <td><strong>d</strong></td>
      <td> 3</td>
      <td> 4</td>
    </tr>
    <tr>
      <td><strong>b</strong></td>
      <td><strong>d</strong></td>
      <td> 5</td>
      <td> 6</td>
    </tr>
  </tbody>
</table>


```
s_1 = s.apply(lambda s: pd.Series({'min': s.min(), 'max': s.max()}), 1)
```

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>max</th>
      <th>min</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>(a, c)</strong></td>
      <td> 2</td>
      <td> 1</td>
    </tr>
    <tr>
      <td><strong>(a, d)</strong></td>
      <td> 4</td>
      <td> 3</td>
    </tr>
    <tr>
      <td><strong>(b, d)</strong></td>
      <td> 6</td>
      <td> 5</td>
    </tr>
  </tbody>
</table>



Discussion:
Thanks for this.

PR shortly with fix.


Resolving patch:
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -4162,7 +4162,7 @@ def _apply_standard(self, func, axis, ignore_failures=False):
                     successes.append(i)
                 except Exception:
                     pass
-            # so will work with MultiIndex, need test
+            # so will work with MultiIndex
             if len(successes) < len(res_index):
                 res_index = res_index.take(successes)
         else:
@@ -4181,6 +4181,7 @@ def _apply_standard(self, func, axis, ignore_failures=False):
                     pass
                 raise e
 
+
         if len(results) > 0 and _is_sequence(results[0]):
             if not isinstance(results[0], Series):
                 index = res_columns
@@ -4188,8 +4189,7 @@ def _apply_standard(self, func, axis, ignore_failures=False):
                 index = None
 
             result = self._constructor(data=results, index=index)
-            result.rename(columns=dict(zip(range(len(res_index)), res_index)),
-                          inplace=True)
+            result.columns = res_index
 
             if axis == 1:
                 result = result.T
@@ -4199,6 +4199,7 @@ def _apply_standard(self, func, axis, ignore_failures=False):
         else:
             s = Series(results)
             s.index = res_index
+
             return s
 
     def _apply_broadcast(self, func, axis):


Test patch:
diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py
--- a/pandas/tests/test_frame.py
+++ b/pandas/tests/test_frame.py
@@ -7262,6 +7262,13 @@ def test_apply_attach_name(self):
                              columns=self.frame.columns)
         assert_frame_equal(result, expected)
 
+    def test_apply_multi_index(self):
+        s = DataFrame([[1,2], [3,4], [5,6]])
+        s.index = MultiIndex.from_arrays([['a','a','b'], ['c','d','d']])
+        s.columns = ['col1','col2']
+        res = s.apply(lambda x: Series({'min': min(x), 'max': max(x)}), 1)
+        self.assert_(isinstance(res.index, MultiIndex))
+
     def test_applymap(self):
         applied = self.frame.applymap(lambda x: x * 2)
         assert_frame_equal(applied, self.frame * 2)