def combine_vars(data, environment=None, vars=None, drop=True):
    """
    Base layout function that generates all combinations of data
    needed for facetting
    The first data frame in the list should be the default data
    for the plot. Other data frames in the list are ones that are
    added to the layers.
    """
    if not vars:
        return pd.DataFrame()

    # For each layer, compute the facet values
    values = [eval_facet_vars(df, vars, environment)
              for df in data if df is not None]

    # Form the base data frame which contains all combinations
    # of facetting variables that appear in the data
    has_all = [x.shape[1] == len(vars) for x in values]
    if not any(has_all):
        raise PlotnineError(
            "At least one layer must contain all variables " +
            "used for facetting")
    base = pd.concat([x for i, x in enumerate(values) if has_all[i]],
                     axis=0)
    base = base.drop_duplicates()

    if not drop:
        base = unique_combs(base)

    # sorts according to order of factor levels
    base = base.sort_values(list(base.columns))

    # Systematically add on missing combinations
    for i, value in enumerate(values):
        if has_all[i] or len(value.columns) == 0:
            continue
        old = base.loc[:, base.columns - value.columns]
        new = value.loc[:, base.columns & value.columns].drop_duplicates()
        if not drop:
            new = unique_combs(new)
        base = base.append(cross_join(old, new), ignore_index=True)

    if len(base) == 0:
        raise PlotnineError(
            "Faceting variables must have at least one value")

    base = base.reset_index(drop=True)
    return base
Base layout function that generates all combinations of data
    needed for facetting
    The first data frame in the list should be the default data
    for the plot. Other data frames in the list are ones that are
    added to the layers.