Repository: modin-project/modin

Issue:
GroupBy throws an assertion error when meets 'by-frame' with `FrameNode`
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Any
- **Modin version** (`modin.__version__`): ebd07ddf14a68d1db42b5c5bbb0c39699c16034a
- **Python version**: 3.7.5
- **Code we can use to reproduce**:
```python
import modin.pandas as pd

def get_op(obj):
    return type(obj._query_compiler._modin_frame._op).__name__

ser = pd.Series([1, 1, 2, 2])
print(f"Initial op node: {get_op(ser)}") # TransformNode (if we do groupby with this type of node it performs well)

ser.index
print(f"Op node after triggering computation: {get_op(ser)}") # FrameNode

# Trying to pass frame with `op = FrameNode` as 'by'
res = ser.groupby(ser).sum() # AssertionError
print(res)
```

Output:
```
Initial op node: TransformNode
Op node after triggering computation: FrameNode
Traceback (most recent call last):
  File "kek.py", line 15, in <module>
    res = ser.groupby(ser).sum()
  File "/localdisk1/dchigare/repos/modin_bp/modin/pandas/groupby.py", line 556, in sum
    **kwargs,
  File "/localdisk1/dchigare/repos/modin_bp/modin/pandas/groupby.py", line 886, in _wrap_aggregation
    drop=self._drop,
  File "/localdisk1/dchigare/repos/modin_bp/modin/experimental/backends/omnisci/query_compiler.py", line 96, in method_wrapper
    return method(self, *args, **kwargs)
  File "/localdisk1/dchigare/repos/modin_bp/modin/experimental/backends/omnisci/query_compiler.py", line 315, in groupby_sum
    by, axis, "sum", groupby_args, **kwargs
  File "/localdisk1/dchigare/repos/modin_bp/modin/experimental/engines/omnisci_on_native/frame/data.py", line 461, in groupby_agg
    assert isinstance(by_frame._op, (TransformNode)), "unexpected by_frame"
AssertionError: unexpected by_frame
```

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
The described `AssertionError` happens here:
https://github.com/modin-project/modin/blob/ebd07ddf14a68d1db42b5c5bbb0c39699c16034a/modin/experimental/engines/omnisci_on_native/frame/data.py#L458-L460
There is a strict type-checking guarding 'by' from being a complex expression, however 'TransformNode' is not the only 'simple' expression, we have to expand the list of allowed nodes to be groupby keys so the related code work well



Discussion:

Resolving patch:
diff --git a/modin/experimental/engines/omnisci_on_native/frame/data.py b/modin/experimental/engines/omnisci_on_native/frame/data.py
--- a/modin/experimental/engines/omnisci_on_native/frame/data.py
+++ b/modin/experimental/engines/omnisci_on_native/frame/data.py
@@ -457,7 +457,13 @@ def groupby_agg(self, by, axis, agg, groupby_args, **kwargs):
 
         # Create new base where all required columns are computed. We don't allow
         # complex expressions to be a group key or an aggeregate operand.
-        assert isinstance(by_frame._op, TransformNode), "unexpected by_frame"
+        allowed_nodes = (FrameNode, TransformNode)
+        if not isinstance(by_frame._op, allowed_nodes):
+            raise NotImplementedError(
+                "OmniSci doesn't allow complex expression to be a group key. "
+                f"The only allowed frame nodes are: {tuple(o.__name__ for o in allowed_nodes)}, "
+                f"met '{type(by_frame._op).__name__}'."
+            )
 
         col_to_delete_template = "__delete_me_{name}"
 


Test patch:
diff --git a/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py b/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py
--- a/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py
+++ b/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py
@@ -42,6 +42,7 @@
 from modin.experimental.engines.omnisci_on_native.frame.partition_manager import (
     OmnisciOnNativeFramePartitionManager,
 )
+from modin.experimental.engines.omnisci_on_native.frame.df_algebra import FrameNode
 
 
 def set_execution_mode(frame, mode, recursive=False):
@@ -875,6 +876,27 @@ def dict_agg_all_cols(df, **kwargs):
 
         run_and_compare(dict_agg_all_cols, data=self.data)
 
+    # modin-issue#3461
+    def test_groupby_pure_by(self):
+        data = [1, 1, 2, 2]
+        # Test when 'by' is a 'TransformNode'
+        run_and_compare(lambda df: df.groupby(df).sum(), data=data, force_lazy=True)
+
+        # Test when 'by' is a 'FrameNode'
+        md_ser, pd_ser = pd.Series(data), pandas.Series(data)
+
+        md_ser._query_compiler._modin_frame._execute()
+        assert isinstance(
+            md_ser._query_compiler._modin_frame._op, FrameNode
+        ), "Triggering execution of the Modin frame supposed to set 'FrameNode' as a frame's op"
+
+        set_execution_mode(md_ser, "lazy")
+        md_res = md_ser.groupby(md_ser).sum()
+        set_execution_mode(md_res, None)
+
+        pd_res = pd_ser.groupby(pd_ser).sum()
+        df_equals(md_res, pd_res)
+
     taxi_data = {
         "a": [1, 1, 2, 2],
         "b": [11, 21, 12, 11],