Convert rect data to polygons

    Paramters
    ---------
    df : dataframe
        Dataframe with *xmin*, *xmax*, *ymin* and *ymax* columns,
        plus others for aesthetics ...

    Returns
    -------
    data : dataframe
        Dataframe with *x* and *y* columns, plus others for
        aesthetics ...

def _rectangles_to_polygons(df):
    """
    Convert rect data to polygons

    Paramters
    ---------
    df : dataframe
        Dataframe with *xmin*, *xmax*, *ymin* and *ymax* columns,
        plus others for aesthetics ...

    Returns
    -------
    data : dataframe
        Dataframe with *x* and *y* columns, plus others for
        aesthetics ...
    """
    n = len(df)

    # Helper indexing arrays
    xmin_idx = np.tile([True, True, False, False], n)
    xmax_idx = ~xmin_idx
    ymin_idx = np.tile([True, False, False, True], n)
    ymax_idx = ~ymin_idx

    # There are 2 x and 2 y values for each of xmin, xmax, ymin & ymax
    # The positions are as layed out in the indexing arrays
    # x and y values
    x = np.empty(n*4)
    y = np.empty(n*4)
    x[xmin_idx] = df['xmin'].repeat(2)
    x[xmax_idx] = df['xmax'].repeat(2)
    y[ymin_idx] = df['ymin'].repeat(2)
    y[ymax_idx] = df['ymax'].repeat(2)

    # Aesthetic columns and others
    other_cols = df.columns.difference(
        ['x', 'y', 'xmin', 'xmax', 'ymin', 'ymax'])
    d = {col: np.repeat(df[col].values, 4) for col in other_cols}
    data = pd.DataFrame({
        'x': x,
        'y': y,
        **d
    })
    return data