code: def test_complex_groupby(self):
      df = self.data
  
      @pandas_udf(
          "id long, v int, norm double", PandasUDFType.GROUPED_MAP
      )
      def normalize(pdf):
          v = pdf.v
          return pdf.assign(norm=(v - v.mean()) / v.std())
  
      result = (
          df.groupby(col("id") % 2 == 0)
          .apply(normalize)
          .sort("id", "v")
          .toPandas()
      )
      pdf = df.toPandas()
      expected = pdf.groupby(pdf["id"] % 2 == 0, as_index=False).apply(
          normalize.func
      )
      expected = expected.sort_values(["id", "v"]).reset_index(
          drop=True
      )
      expected = expected.assign(norm=expected.norm.astype("float64"))
      assert_frame_equal(expected, result)
  
imports: import datetime
  import unittest
  from collections import OrderedDict
  from decimal import Decimal
  from typing import cast
  from pyspark.sql import Row
  from pyspark.sql.functions import array, explode, col, lit, udf, sum, pandas_udf, PandasUDFType, window
  from pyspark.sql.types import IntegerType, DoubleType, ArrayType, BinaryType, ByteType, LongType, DecimalType, ShortType, FloatType, StringType, BooleanType, StructType, StructField, NullType, MapType, YearMonthIntervalType
  from pyspark.errors import PythonException, PySparkTypeError
  from pyspark.testing.sqlutils import ReusedSQLTestCase, have_pandas, have_pyarrow, pandas_requirement_message, pyarrow_requirement_message
  from pyspark.testing.utils import QuietTest
label_desc: Use image node_id 8 for calling the GroupedApplyInPandasTestsMixin obj's underlying member method code with example usage: obj.test_complex_groupby() and returns: pdf