# Buggy code
def _infer_df_func_returns(self, in_groupby, in_df, dtypes, index):
    index_value, output_type, new_dtypes = None, None, None

    try:
        if in_df.op.output_types[0] == OutputType.dataframe:
            test_df = build_df(in_df, size=2)
        else:
            test_df = build_series(in_df, size=2, name=in_df.name)

        selection = getattr(in_groupby.op, "selection", None)
        if selection:
            test_df = test_df[selection]

        with np.errstate(all="ignore"):
            infer_df = self.func(test_df, *self.args, **self.kwds)

        # todo return proper index when sort=True is implemented
        index_value = parse_index(None, in_df.key, self.func)

        if isinstance(infer_df, pd.DataFrame):
            output_type = output_type or OutputType.dataframe
            new_dtypes = new_dtypes or infer_df.dtypes
        elif isinstance(infer_df, pd.Series):
            output_type = output_type or OutputType.series
            new_dtypes = new_dtypes or (infer_df.name, infer_df.dtype)
        else:
            output_type = OutputType.series
            new_dtypes = (None, pd.Series(infer_df).dtype)
    except:  # noqa: E722  # nosec
        pass

    self.output_types = [output_type] if not self.output_types else self.output_types
    dtypes = new_dtypes if dtypes is None else dtypes
    index_value = index_value if index is None else parse_index(index)
    return dtypes, index_value


# Traceback (AssertionError)
Traceback (most recent call last):
File "/Users/wenjun/miniconda3/lib/python3.8/unittest/case.py", line 60, in testPartExecutor
yield
File "/Users/wenjun/miniconda3/lib/python3.8/unittest/case.py", line 676, in run
self._callTestMethod(testMethod)
File "/Users/wenjun/miniconda3/lib/python3.8/unittest/case.py", line 633, in _callTestMethod
method()
File "/Users/wenjun/Code/mars/mars/dataframe/groupby/tests/test_groupby_execution.py", line 401, in testGroupByApply
pd.testing.assert_frame_equal(self.executor.execute_dataframe(applied, concat=True)[0],
File "/Users/wenjun/Code/mars/mars/tests/core.py", line 686, in execute_tileable
result = super().execute_tileable(tileable, *args, **kwargs)
File "/Users/wenjun/Code/mars/mars/utils.py", line 439, in _inner
return func(*args, **kwargs)
File "/Users/wenjun/Code/mars/mars/executor.py", line 720, in execute_tileable
ret = self.execute_graph(chunk_graph, result_keys, n_parallel=n_parallel or n_thread,
File "/Users/wenjun/Code/mars/mars/tests/core.py", line 673, in execute_graph
return super().execute_graph(graph, keys, **kw)
File "/Users/wenjun/Code/mars/mars/executor.py", line 693, in execute_graph
res = graph_execution.execute(retval)
File "/Users/wenjun/Code/mars/mars/executor.py", line 574, in execute
future.result()
File "/Users/wenjun/miniconda3/lib/python3.8/concurrent/futures/_base.py", line 439, in result
return self.__get_result()
File "/Users/wenjun/miniconda3/lib/python3.8/concurrent/futures/_base.py", line 388, in __get_result
raise self._exception
File "/Users/wenjun/miniconda3/lib/python3.8/concurrent/futures/thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "/Users/wenjun/Code/mars/mars/tests/core.py", line 591, in _execute_operand
super()._execute_operand(op)
File "/Users/wenjun/Code/mars/mars/utils.py", line 439, in _inner
return func(*args, **kwargs)
File "/Users/wenjun/Code/mars/mars/executor.py", line 446, in _execute_operand
self.handle_op(first_op, results, self._mock)
File "/Users/wenjun/Code/mars/mars/executor.py", line 378, in handle_op
return Executor.handle(*args, **kw)
File "/Users/wenjun/Code/mars/mars/executor.py", line 644, in handle
return runner(results, op)
File "/Users/wenjun/Code/mars/mars/dataframe/groupby/apply.py", line 63, in execute
assert len(applied.index) == 1
AssertionError

# Fixed code
def _infer_df_func_returns(self, in_groupby, in_df, dtypes, index):
    index_value, output_type, new_dtypes = None, None, None

    try:
        if in_df.op.output_types[0] == OutputType.dataframe:
            test_df = build_df(in_df, size=2)
        else:
            test_df = build_series(in_df, size=2, name=in_df.name)

        selection = getattr(in_groupby.op, "selection", None)
        if selection:
            test_df = test_df[selection]

        with np.errstate(all="ignore"):
            infer_df = self.func(test_df, *self.args, **self.kwds)

        # todo return proper index when sort=True is implemented
        index_value = parse_index(None, in_df.key, self.func)

        if infer_df is None:
            output_type = get_output_types(in_df)[0]
            index_value = parse_index(pd.Index([], dtype=np.object))
            if output_type == OutputType.dataframe:
                new_dtypes = pd.Series([], index=pd.Index([]))
            else:
                new_dtypes = (None, np.dtype("O"))
        elif isinstance(infer_df, pd.DataFrame):
            output_type = output_type or OutputType.dataframe
            new_dtypes = new_dtypes or infer_df.dtypes
        elif isinstance(infer_df, pd.Series):
            output_type = output_type or OutputType.series
            new_dtypes = new_dtypes or (infer_df.name, infer_df.dtype)
        else:
            output_type = OutputType.series
            new_dtypes = (None, pd.Series(infer_df).dtype)
    except:  # noqa: E722  # nosec
        pass

    self.output_types = [output_type] if not self.output_types else self.output_types
    dtypes = new_dtypes if dtypes is None else dtypes
    index_value = index_value if index is None else parse_index(index)
    return dtypes, index_value