Repository: modin-project/modin

Issue:
reset_index() on a MultiIndex does not create multiple columns
### Describe the problem

See source code below. Behavior does not match pandas.

### Source code / logs
**Modin**
```python
import modin.pandas as pd
import numpy as np

df = pd.DataFrame(frame_data).add_prefix("col")
df.groupby(["col1", "col2"]).count().reset_index().columns
```
**pandas**
```python
import pandas
import numpy as np

df = pandas.DataFrame(frame_data).add_prefix("col")
df.groupby(["col1", "col2"]).count().reset_index().columns
```


Discussion:

Resolving patch:
diff --git a/modin/data_management/query_compiler/pandas_query_compiler.py b/modin/data_management/query_compiler/pandas_query_compiler.py
--- a/modin/data_management/query_compiler/pandas_query_compiler.py
+++ b/modin/data_management/query_compiler/pandas_query_compiler.py
@@ -837,10 +837,18 @@ def reset_index(self, **kwargs):
         drop = kwargs.get("drop", False)
         new_index = pandas.RangeIndex(len(self.index))
         if not drop:
-            new_column_name = "index" if "index" not in self.columns else "level_0"
-            new_columns = self.columns.insert(0, new_column_name)
-            result = self.insert(0, new_column_name, self.index)
-            return self.__constructor__(result.data, new_index, new_columns)
+            if isinstance(self.index, pandas.MultiIndex):
+                # TODO (devin-petersohn) ensure partitioning is properly aligned
+                new_column_names = pandas.Index(self.index.names)
+                new_columns = new_column_names.append(self.columns)
+                index_data = pandas.DataFrame(list(zip(*self.index))).T
+                result = self.data.from_pandas(index_data).concat(1, self.data)
+                return self.__constructor__(result, new_index, new_columns)
+            else:
+                new_column_name = "index" if "index" not in self.columns else "level_0"
+                new_columns = self.columns.insert(0, new_column_name)
+                result = self.insert(0, new_column_name, self.index)
+                return self.__constructor__(result.data, new_index, new_columns)
         else:
             # The copies here are to ensure that we do not give references to
             # this object for the purposes of updates.
diff --git a/modin/pandas/dataframe.py b/modin/pandas/dataframe.py
--- a/modin/pandas/dataframe.py
+++ b/modin/pandas/dataframe.py
@@ -3210,7 +3210,11 @@ def reset_index(
         # Error checking for matching Pandas. Pandas does not allow you to
         # insert a dropped index into a DataFrame if these columns already
         # exist.
-        if not drop and all(n in self.columns for n in ["level_0", "index"]):
+        if (
+            not drop
+            and not isinstance(self.index, pandas.MultiIndex)
+            and all(n in self.columns for n in ["level_0", "index"])
+        ):
             raise ValueError("cannot insert level_0, already exists")
         new_query_compiler = self._query_compiler.reset_index(drop=drop, level=level)
         return self._create_dataframe_from_compiler(new_query_compiler, inplace)


Test patch:
diff --git a/modin/pandas/test/test_dataframe.py b/modin/pandas/test/test_dataframe.py
--- a/modin/pandas/test/test_dataframe.py
+++ b/modin/pandas/test/test_dataframe.py
@@ -3651,3 +3651,14 @@ def test_get_dummies():
     ray_df = pd.DataFrame(frame_data)
     pd_df = pandas.DataFrame(frame_data)
     assert ray_df_equals_pandas(pd.get_dummies(ray_df), pandas.get_dummies(pd_df))
+
+
+def test_reset_index_with_multi_index():
+    frame_data = np.random.randint(0, 100, size=(2 ** 10, 2 ** 6))
+    md_df = pd.DataFrame(frame_data).add_prefix("col")
+    pd_df = pandas.DataFrame(frame_data).add_prefix("col")
+
+    md_cols = md_df.groupby(["col1", "col2"]).count().reset_index().columns
+    pd_cols = pd_df.groupby(["col1", "col2"]).count().reset_index().columns
+
+    assert md_cols.equals(pd_cols)