docs: def assess_quality(feed: "Feed") -> DataFrame:
      """
      Return a DataFrame of various feed indicators and values,
      e.g. number of trips missing shapes.
  
      Parameters
      ----------
      feed : Feed
  
      Returns
      -------
      DataFrame
          The columns are
  
          - ``'indicator'``: string; name of an indicator, e.g. 'num_routes'
          - ``'value'``: value of the indicator, e.g. 27
  
      Notes
      -----
      - An odd function, but useful to see roughly how broken a feed is
      - Not a GTFS validator
  
      """
      d = OrderedDict()
  
      # Count duplicate route short names
      r = feed.routes
      dup = r.duplicated(subset=["route_short_name"])
      n = dup[dup].count()
      d["num_route_short_names_duplicated"] = n
      d["frac_route_short_names_duplicated"] = n / r.shape[0]
  
      # Count stop times missing shape_dist_traveled values
      st = feed.stop_times.sort_values(["trip_id", "stop_sequence"])
      if "shape_dist_traveled" in st.columns:
          # Count missing distances
          n = st[st["shape_dist_traveled"].isnull()].shape[0]
          d["num_stop_time_dists_missing"] = n
          d["frac_stop_time_dists_missing"] = n / st.shape[0]
      else:
          d["num_stop_time_dists_missing"] = st.shape[0]
          d["frac_stop_time_dists_missing"] = 1
  
      # Count direction_ids missing
      t = feed.trips
      if "direction_id" in t.columns:
          n = t[t["direction_id"].isnull()].shape[0]
          d["num_direction_ids_missing"] = n
          d["frac_direction_ids_missing"] = n / t.shape[0]
      else:
          d["num_direction_ids_missing"] = t.shape[0]
          d["frac_direction_ids_missing"] = 1
  
      # Count trips missing shapes
      if feed.shapes is not None:
          n = t[t["shape_id"].isnull()].shape[0]
      else:
          n = t.shape[0]
      d["num_trips_missing_shapes"] = n
      d["frac_trips_missing_shapes"] = n / t.shape[0]
  
      # Count missing departure times
      n = st[st["departure_time"].isnull()].shape[0]
      d["num_departure_times_missing"] = n
      d["frac_departure_times_missing"] = n / st.shape[0]
  
      # Count missing first departure times missing
      g = st.groupby("trip_id").first().reset_index()
      n = g[g["departure_time"].isnull()].shape[0]
      d["num_first_departure_times_missing"] = n
      d["frac_first_departure_times_missing"] = n / st.shape[0]
  
      # Count missing last departure times
      g = st.groupby("trip_id").last().reset_index()
      n = g[g["departure_time"].isnull()].shape[0]
      d["num_last_departure_times_missing"] = n
      d["frac_last_departure_times_missing"] = n / st.shape[0]
  
      # Opine
      if (
          (d["frac_first_departure_times_missing"] >= 0.1)
          or (d["frac_last_departure_times_missing"] >= 0.1)
          or d["frac_trips_missing_shapes"] >= 0.8
      ):
          d["assessment"] = "bad feed"
      elif (
          d["frac_direction_ids_missing"]
          or d["frac_stop_time_dists_missing"]
          or d["num_route_short_names_duplicated"]
      ):
          d["assessment"] = "probably a fixable feed"
      else:
          d["assessment"] = "good feed"
  
      f = pd.DataFrame(list(d.items()), columns=["indicator", "value"])
  
      return f