<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def summarize(feed: "Feed", table: str = None) -> DataFrame: """ Return a DataFrame summarizing all GTFS tables in the given feed or in the given table if specified. Parameters feed : Feed table : string A GTFS table name, e.g. ``'stop_times'`` Returns ------- DataFrame Columns are - ``'table'``: name of the GTFS table, e.g. ``'stops'`` - ``'column'``: name of a column in the table, e.g. ``'stop_id'`` - ``'num_values'``: number of values in the column - ``'num_nonnull_values'``: number of nonnull values in the column - ``'num_unique_values'``: number of unique values in the column, excluding null values - ``'min_value'``: minimum value in the column - ``'max_value'``: maximum value in the column Notes ----- - If the table is not in the feed, then return an empty DataFrame - If the table is not valid, raise a ValueError """

    gtfs_tables = cs.GTFS_REF.table.unique()

    if table is not None:
        if table not in gtfs_tables:
            raise ValueError(f"{table} is not a GTFS table")
        else:
            tables = [table]
    else:
        tables = gtfs_tables

    frames = []
    for table in tables:
        f = getattr(feed, table)
        if f is None:
            continue

        def my_agg(col):
            d = {}
            d["column"] = col.name
            d["num_values"] = col.size
            d["num_nonnull_values"] = col.count()
            d["num_unique_values"] = col.nunique()
            d["min_value"] = col.dropna().min()
            d["max_value"] = col.dropna().max()
            return pd.Series(d)

        g = f.apply(my_agg).T.reset_index(drop=True)
        g["table"] = table
        frames.append(g)

    cols = [
        "table",
        "column",
        "num_values",
        "num_nonnull_values",
        "num_unique_values",
        "min_value",
        "max_value",
    ]

    if not frames:
        f = pd.DataFrame()
    else:
        f = pd.concat(frames)
        # Rearrange columns
        f = f[cols].copy()

    return f