def table_reprocess(cfg, df):
    """
    Reprocesses a table with the given configuration, mainly by filling nas
    with the given configuration.

    Parameters
    ----------
    cfg : dict
        The configuration is specified as a nested dictionary, javascript
        style, and a simple config is given below.  Most parameters should be
        fairly self-explanatory.  "filter" filters the dataframe using the
        query command in Pandas.  The "fill_nas" parameter is another
        dictionary which takes each column and specifies how to fill nas -
        options include "drop", "zero", "median", "mode", and "mean".  The
        "type" must also be specified since items like "median" usually
        return floats but the result is often desired to be an "int" - the
        type is thus specified to avoid ambiguity.::

            {
                "filter": "building_type_id >= 1 and building_type_id <= 14",
                "fill_nas": {
                    "building_type_id": {
                        "how": "drop",
                        "type": "int"
                    },
                    "residential_units": {
                        "how": "zero",
                        "type": "int"
                    },
                    "year_built": {
                        "how": "median",
                        "type": "int"
                    },
                    "building_type_id": {
                        "how": "mode",
                        "type": "int"
                    }
                }
            }

    df : DataFrame to process

    Returns
    -------
    New DataFrame which is reprocessed according the configuration
    """
    df_cnt = len(df)
    if 'filter' in cfg:
        df = df.query(cfg['filter'])
    assert 'fill_nas' in cfg
    cfg = cfg['fill_nas']
    for fname in cfg:
        filltyp, dtyp = cfg[fname]['how'], cfg[fname]['type']
        s_cnt = df[fname].count()
        fill_cnt = df_cnt - s_cnt
        if filltyp == 'zero':
            val = 0
        elif filltyp == 'mode':
            val = df[fname].dropna().value_counts().idxmax()
        elif filltyp == 'median':
            val = df[fname].dropna().quantile()
        elif filltyp == 'mean':
            val = df[fname].dropna().mean()
        elif filltyp == 'drop':
            df = df.dropna(subset=[fname])
        else:
            assert 0, 'Fill type not found!'
        print('Filling column {} with value {} ({} values)'.format(fname,
            val, fill_cnt))
        df[fname] = df[fname].fillna(val).astype(dtyp)
    return df
