def get_feature_size_by_class(df, class_col, features, normalize='class'):
    """
    Given pandas.DataFrame, class column name, and feature column
    name, return:

        - pd.crosstab(df.class_col, df.feature).stack()

    Works differently from `pandas.crosstab` if multiple features passed.
    Note that this function makes the most sense for categorical 
    features.

    Parameters
    ----------

    df : pandas.DataFrame
        DataFrame on which this function will operate.

    class_col : str
        Column name for the class / target.

    features : str or list
        Column name(s) for the feature.

    normalize : str, "class" or "all" or None (default="class")
        Whether to normalize counts. "class" means normalize counts within a 
        class value by the total counts in that group. "all" means normalize 
        by the length of `df`. `None` means do not normalize.

    Return
    ------

    pandas.DataFrame of size figures.
    """
    if isinstance(features, str):
        features = [features]
    elif not isinstance(features, list):
        raise TypeError('Must pass str or list for `features`.')
    to_group_by = [class_col] + features
    to_return = df[to_group_by].groupby(to_group_by).size().rename('cnt'
        ).to_frame()
    if normalize == 'all':
        to_return = (to_return / len(df)).rename(columns={'cnt': 'ratio'})
    elif normalize == 'class':
        denominators = to_return.groupby(level=0).sum().rename(columns={
            'cnt': 'cnt_cls_val'}).reset_index()
        to_return = to_return.reset_index().merge(denominators, on=class_col
            ).set_index(to_group_by)
        to_return = to_return.cnt.divide(to_return.cnt_cls_val).rename('ratio'
            ).to_frame()
    elif normalize is None:
        pass
    else:
        raise ValueError('Improper value passed for `normalize`.')
    return to_return
