code: def test_complex_groupby(self):
      df = self.data
      sum_udf = self.pandas_agg_sum_udf
      plus_one = self.python_plus_one
      plus_two = self.pandas_scalar_plus_two
  
      # groupby one expression
      result1 = df.groupby(df.v % 2).agg(sum_udf(df.v))
      expected1 = df.groupby(df.v % 2).agg(sum(df.v))
  
      # empty groupby
      result2 = df.groupby().agg(sum_udf(df.v))
      expected2 = df.groupby().agg(sum(df.v))
  
      # groupby one column and one sql expression
      result3 = (
          df.groupby(df.id, df.v % 2)
          .agg(sum_udf(df.v))
          .orderBy(df.id, df.v % 2)
      )
      expected3 = (
          df.groupby(df.id, df.v % 2)
          .agg(sum(df.v))
          .orderBy(df.id, df.v % 2)
      )
  
      # groupby one python UDF
      result4 = (
          df.groupby(plus_one(df.id))
          .agg(sum_udf(df.v))
          .sort("plus_one(id)")
      )
      expected4 = (
          df.groupby(plus_one(df.id))
          .agg(sum(df.v))
          .sort("plus_one(id)")
      )
  
      # groupby one scalar pandas UDF
      result5 = (
          df.groupby(plus_two(df.id)).agg(sum_udf(df.v)).sort("sum(v)")
      )
      expected5 = (
          df.groupby(plus_two(df.id)).agg(sum(df.v)).sort("sum(v)")
      )
  
      # groupby one expression and one python UDF
      result6 = (
          df.groupby(df.v % 2, plus_one(df.id))
          .agg(sum_udf(df.v))
          .sort(["(v % 2)", "plus_one(id)"])
      )
      expected6 = (
          df.groupby(df.v % 2, plus_one(df.id))
          .agg(sum(df.v))
          .sort(["(v % 2)", "plus_one(id)"])
      )
  
      # groupby one expression and one scalar pandas UDF
      result7 = (
          df.groupby(df.v % 2, plus_two(df.id))
          .agg(sum_udf(df.v))
          .sort(["sum(v)", "plus_two(id)"])
      )
      expected7 = (
          df.groupby(df.v % 2, plus_two(df.id))
          .agg(sum(df.v))
          .sort(["sum(v)", "plus_two(id)"])
      )
  
      assert_frame_equal(expected1.toPandas(), result1.toPandas())
      assert_frame_equal(expected2.toPandas(), result2.toPandas())
      assert_frame_equal(expected3.toPandas(), result3.toPandas())
      assert_frame_equal(expected4.toPandas(), result4.toPandas())
      assert_frame_equal(expected5.toPandas(), result5.toPandas())
      assert_frame_equal(expected6.toPandas(), result6.toPandas())
      assert_frame_equal(expected7.toPandas(), result7.toPandas())
  
imports: import unittest
  from typing import cast
  from pyspark.rdd import PythonEvalType
  from pyspark.sql import Row
  from pyspark.sql.functions import array, explode, col, lit, mean, sum, udf, pandas_udf, PandasUDFType
  from pyspark.sql.types import ArrayType, YearMonthIntervalType
  from pyspark.errors import AnalysisException, PySparkNotImplementedError, PythonException
  from pyspark.testing.sqlutils import ReusedSQLTestCase, have_pandas, have_pyarrow, pandas_requirement_message, pyarrow_requirement_message
  from pyspark.testing.utils import QuietTest, assertDataFrameEqual
label_desc: Use image node_id 15 for calling the GroupedAggPandasUDFTestsMixin obj's underlying member method code with example usage: obj.test_complex_groupby() without return types