def remove_bad_rows(df):
    """Based on ISD documentation, remove data with the following sources, report types, call signs, and QC.

    ISD docs: https://www1.ncdc.noaa.gov/pub/data/noaa/isd-format-document.pdf

    # remove SOURCE:
    # 2: failed cross checks
    # A: failed cross checks
    # B: failed cross checks
    # O: Summary observation created by NCEI using hourly observations that
    #    may not share the same data source flag
    # 9: missing

    # remove REPORT_TYPE
    # 99999: missing

    # remove CALL_SIGN
    # 99999: missing

    # remove QUALITY_CONTROL
    # V01: no quality control
    """
    bad_idx = ((df['SOURCE'].astype(str) == '2') |
               (df['SOURCE'].astype(str) == 'A') |
               (df['SOURCE'].astype(str) == 'B') |
               (df['SOURCE'].astype(str) == 'O') |
               (df['SOURCE'].astype(str) == '9') |
               (df['REPORT_TYPE'].astype(str) == '99999') |
               (df['CALL_SIGN'].astype(str) == '99999') |
               (df['QUALITY_CONTROL'].astype(str) == 'V010'))

    return df[~bad_idx]