def clean_visits(data, test, n_visits=100):
    """
    Drops rows of `data` with too few entries for given `test`

    Parameters
    ----------
    data : pandas.DataFrame
        Must have at least columns 'visit' and `test`
    test : str
        Column of `data` used to determine which rows to drop
    n_visits : int, optional
        Minimum number of participants with data for `test` at a given visit
        required to retain that visit

    Returns
    -------
    data : pandas.DataFrame
        Cleaned input `data`
    """

    if test not in data.columns:
        raise ValueError('Provide test "{}" not in data'.format(test))

    # determine which vists have sufficient datapoints
    data = data.dropna(subset=[test])
    visits = data.groupby('visit').count()
    visits = list(visits[visits['participant'] > n_visits].index)

    # drop "bad" visits and remove those as categories; also, convert the
    # visits column to a numerical value
    data = data.query(f'visit in {visits}')
    visit_codes = data['visit'].cat.remove_unused_categories().cat.codes
    data = data.assign(visit=visit_codes)

    return data