def add_margins(df, vars, margins=True):
    """
    Add margins to a data frame.

    All margining variables will be converted to factors.

    Parameters
    ----------
    df : dataframe
        input data frame

    vars : list
        a list of 2 lists | tuples vectors giving the
        variables in each dimension

    margins : bool | list
        variable names to compute margins for.
        True will compute all possible margins.
    """
    margin_vars = _margins(vars, margins)
    if not margin_vars:
        return df

    # create margin dataframes
    margin_dfs = [df]
    for vlst in margin_vars[1:]:
        dfx = df.copy()
        for v in vlst:
            dfx.loc[0:, v] = '(all)'
        margin_dfs.append(dfx)

    merged = pd.concat(margin_dfs, axis=0)
    merged.reset_index(drop=True, inplace=True)

    # All margin columns become categoricals. The margin indicator
    # (all) needs to be added as the last level of the categories.
    categories = {}
    for v in itertools.chain(*vars):
        col = df[v]
        if not pdtypes.is_categorical_dtype(df[v].dtype):
            col = pd.Categorical(df[v])
        categories[v] = col.categories
        if '(all)' not in categories[v]:
            categories[v] = categories[v].insert(
                len(categories[v]), '(all)')

    for v in merged.columns.intersection(set(categories)):
        merged[v] = merged[v].astype(
           pdtypes.CategoricalDtype(categories[v]))

    return merged
def add_margins ( df , vars , margins = True ) : margin_vars = _margins ( vars , margins ) if not margin_vars : return df margin_dfs = [ df ] for vlst in margin_vars [ 1 : ] : dfx = df . copy ( ) for v in vlst : dfx . loc [ 0 : , v ] = '(all)' margin_dfs . append ( dfx ) merged = pd . concat ( margin_dfs , axis = 0 ) merged . reset_index ( drop = True , inplace = True ) categories = { } for v in itertools . chain ( * vars ) : col = df [ v ] if not pdtypes . is_categorical_dtype ( df [ v ] . dtype ) : col = pd . Categorical ( df [ v ] ) categories [ v ] = col . categories if '(all)' not in categories [ v ] : categories [ v ] = categories [ v ] . insert ( len ( categories [ v ] ) , '(all)' ) for v in merged . columns . intersection ( set ( categories ) ) : merged [ v ] = merged [ v ] . astype ( pdtypes . CategoricalDtype ( categories [ v ] ) ) return merged
Add margins to a data frame.

    All margining variables will be converted to factors.

    Parameters
    ----------
    df : dataframe
        input data frame

    vars : list
        a list of 2 lists | tuples vectors giving the
        variables in each dimension

    margins : bool | list
        variable names to compute margins for.
        True will compute all possible margins.