def check_frequencies(pfeed, *, as_df=False, include_warnings=False):
    """
    Check that ``pfeed.frequency`` follows the ProtoFeed spec.
    Return a list of problems of the form described in
    :func:`gt.check_table`;
    the list will be empty if no problems are found.
    """
    table = 'frequencies'
    problems = []

    # Preliminary checks
    if pfeed.frequencies is None:
        problems.append(['error', 'Missing table', table, []])
    else:
        f = pfeed.frequencies.copy()
        problems = check_for_required_columns(problems, table, f)
    if problems:
        return gt.format_problems(problems, as_df=as_df)

    if include_warnings:
        problems = check_for_invalid_columns(problems, table, f)

    # Check route_short_name and route_long_name
    for column in ['route_short_name', 'route_long_name']:
        problems = gt.check_column(problems, table, f, column, gt.valid_str,
          column_required=False)

    cond = ~(f['route_short_name'].notnull() | f['route_long_name'].notnull())
    problems = gt.check_table(problems, table, f, cond,
      'route_short_name and route_long_name both empty')

    # Check route_type
    v = lambda x: x in range(8)
    problems = gt.check_column(problems, table, f, 'route_type', v)

    # Check service window ID
    problems = gt.check_column_linked_id(problems, table, f,
      'service_window_id', pfeed.service_windows)

    # Check direction
    v = lambda x: x in range(3)
    problems = gt.check_column(problems, table, f, 'direction', v)

    # Check frequency
    v = lambda x: isinstance(x, int)
    problems = gt.check_column(problems, table, f, 'frequency', v)

    # Check speed
    problems = gt.check_column(problems, table, f, 'speed', valid_speed,
      column_required=False)

    # Check shape ID
    problems = gt.check_column_linked_id(problems, table, f, 'shape_id',
      pfeed.shapes)

    return gt.format_problems(problems, as_df=as_df)
Check that ``pfeed.frequency`` follows the ProtoFeed spec.
    Return a list of problems of the form described in
    :func:`gt.check_table`;
    the list will be empty if no problems are found.