code: def get_bounding_boxes(df_shapes, shape_i_columns):
      '''
      Return a `pandas.DataFrame` indexed by `shape_i_columns` (i.e., each row
      corresponds to a single shape/polygon), containing the following columns:
  
       - `width`: The width of the widest part of the shape.
       - `height`: The height of the tallest part of the shape.
      '''
      xy_groups = df_shapes.groupby(shape_i_columns)[['x', 'y']]
      xy_min = xy_groups.agg('min')
      xy_max = xy_groups.agg('max')
  
      shapes = (xy_max - xy_min).rename(columns={'x': 'width', 'y': 'height'})
      return xy_min.join(shapesf get_bounding_boxes(df_shapes, shape_i_columns):
      '''
      Return a `pandas.DataFrame` indexed by `shape_i_columns` (i.e., each row
      corresponds to a single shape/polygon), containing the following columns:
  
       - `width`: The width of the widest part of the shape.
       - `height`: The height of the tallest part of the shape.
      '''
      xy_groups = df_shapes.groupby(shape_i_columns)[['x', 'y']]
      xy_min = xy_groups.agg('min')
      xy_max = xy_groups.agg('max')
  
      shapes = (xy_max - xy_min).rename(columns={'x': 'width', 'y': 'height'})
      return xy_min.join(shapes)
docs: Return a `pandas.DataFrame` indexed by `shape_i_columns` (i.e., each row
      corresponds to a single shape/polygon), containing the following columns:
  
       - `width`: The width of the widest part of the shape.
       - `height`: The height of the tallest part of the shape.