code: def get_shape_infos(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:
  
       - `area`: The area of the shape.
       - `width`: The width of the widest part of the shape.
       - `height`: The height of the tallest part of the shape.
      '''
      shape_areas = get_shape_areas(df_shapes, shape_i_columns)
      bboxes = get_bounding_boxes(df_shapes, shape_i_columns)
      return bboxes.join(pd.DataFrame(shape_areas)f get_shape_infos(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:
  
       - `area`: The area of the shape.
       - `width`: The width of the widest part of the shape.
       - `height`: The height of the tallest part of the shape.
      '''
      shape_areas = get_shape_areas(df_shapes, shape_i_columns)
      bboxes = get_bounding_boxes(df_shapes, shape_i_columns)
      return bboxes.join(pd.DataFrame(shape_areas))
docs: Return a `pandas.DataFrame` indexed by `shape_i_columns` (i.e., each row
      corresponds to a single shape/polygon), containing the following columns:
  
       - `area`: The area of the shape.
       - `width`: The width of the widest part of the shape.
       - `height`: The height of the tallest part of the shape.