Repository: modin-project/modin

Issue:
groupby(level=0) leads to TypeError: 'NoneType' object is not iterable 
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:  macOS Mojave 10.14.3 (18D109)
- **Modin installed from (source or binary)**: pip
- **Modin version**: 0.4.0
- **Python version**: 3.7.0
- **Exact command to reproduce**: `df.groupby(level=0)`

### Describe the problem
Using `df.grouby(level=0)` to group by index using level param causes error

### Source code / logs
```
import modin.pandas as pd
import numpy as np

test_data = pd.DataFrame({
    'A': 1,
    'B': np.array([3] * 4, dtype='int32')
})
test_data.groupby(level=0)
```
>TypeError                                 Traceback (most recent call last)
<ipython-input-241-fbcec6e80c45> in <module>()
      6     'B': np.array([3] * 4, dtype='int32')
      7 })
----> 8 test_data.groupby(level=0)
>
>~/.pyenv/versions/3.7.0/envs/topic-modeling/lib/python3.7/site-packages/modin/pandas/dataframe.py in groupby(self, by, axis, level, as_index, sort, group_keys, squeeze, observed, **kwargs)
    407             idx_name,
    408             observed=observed,
--> 409             **kwargs
    410         )
    411 
>
>~/.pyenv/versions/3.7.0/envs/topic-modeling/lib/python3.7/site-packages/modin/pandas/groupby.py in __init__(self, df, by, axis, level, as_index, sort, group_keys, squeeze, idx_name, **kwargs)
     42         self._by = by
     43         # This tells us whether or not there are multiple columns/rows in the groupby
---> 44         self._is_multi_by = all(obj in self._df for obj in self._by) and axis == 0
     45         self._level = level
     46         self._kwargs = {
>
>TypeError: 'NoneType' object is not iterable




Discussion:
Hi @izdi thanks for posting!

I can reproduce this issue on the current master, and the fix is relatively simple. I will be able to fix it today, thanks!

Resolving patch:
diff --git a/modin/pandas/groupby.py b/modin/pandas/groupby.py
--- a/modin/pandas/groupby.py
+++ b/modin/pandas/groupby.py
@@ -40,10 +40,14 @@ def __init__(
         self._index = self._query_compiler.index
         self._columns = self._query_compiler.columns
         self._by = by
-        # This tells us whether or not there are multiple columns/rows in the groupby
-        self._is_multi_by = all(obj in self._df for obj in self._by) and axis == 0
+        if level is None:
+            # This tells us whether or not there are multiple columns/rows in the groupby
+            self._is_multi_by = all(obj in self._df for obj in self._by) and axis == 0
+        else:
+            self._is_multi_by = False
         self._level = level
         self._kwargs = {
+            "level": level,
             "sort": sort,
             "as_index": as_index,
             "group_keys": group_keys,
@@ -410,7 +414,7 @@ def _apply_agg_function(self, f, drop=True, **kwargs):
         assert callable(f), "'{0}' object is not callable".format(type(f))
         from .dataframe import DataFrame
 
-        if self._is_multi_by:
+        if self._is_multi_by or self._level is not None:
             return self._default_to_pandas(f, **kwargs)
         # For aggregations, pandas behavior does this for the result.
         # For other operations it does not, so we wait until there is an aggregation to


Test patch:
diff --git a/modin/pandas/test/test_groupby.py b/modin/pandas/test/test_groupby.py
--- a/modin/pandas/test/test_groupby.py
+++ b/modin/pandas/test/test_groupby.py
@@ -801,3 +801,14 @@ def test_groupby_on_index_values_with_loop():
 
     for k in modin_dict:
         ray_df_equals_pandas(modin_dict[k], pandas_dict[k])
+
+
+def test_groupby_multiindex():
+    frame_data = np.random.randint(0, 100, size=(2 ** 6, 2 ** 4))
+    modin_df = pd.DataFrame(frame_data)
+    new_columns = pandas.MultiIndex.from_tuples(
+        [(i // 4, i // 2, i) for i in modin_df.columns]
+    )
+    modin_df.columns = new_columns
+    with pytest.warns(UserWarning):
+        modin_df.groupby(level=0).sum()