docs: def compute_stop_stats_base(
      stop_times_subset: DataFrame,
      trip_subset: DataFrame,
      headway_start_time: str = "07:00:00",
      headway_end_time: str = "19:00:00",
      *,
      split_directions: bool = False,
  ) -> DataFrame:
      """
      Given a subset of a stop times DataFrame and a subset of a trips
      DataFrame, return a DataFrame that provides summary stats about the
      stops in the inner join of the two DataFrames.
  
      Parameters
      ----------
      stop_times_subset : DataFrame
          A valid GTFS stop times table
      trip_subset : DataFrame
          A valid GTFS trips table
      split_directions : boolean
          If ``True``, then separate the stop stats by direction (0 or 1)
          of the trips visiting the stops; otherwise aggregate trips
          visiting from both directions
      headway_start_time : string
          HH:MM:SS time string indicating the start time for computing
          headway stats
      headway_end_time : string
          HH:MM:SS time string indicating the end time for computing
          headway stats
  
      Returns
      -------
      DataFrame
          The columns are
  
          - stop_id
          - direction_id: present if and only if ``split_directions``
          - num_routes: number of routes visiting stop
            (in the given direction)
          - num_trips: number of trips visiting stop
            (in the givin direction)
          - max_headway: maximum of the durations (in minutes)
            between trip departures at the stop between
            ``headway_start_time`` and ``headway_end_time``
          - min_headway: minimum of the durations (in minutes) mentioned
            above
          - mean_headway: mean of the durations (in minutes) mentioned
            above
          - start_time: earliest departure time of a trip from this stop
          - end_time: latest departure time of a trip from this stop
  
  
      Notes
      -----
      - If ``trip_subset`` is empty, then return an empty DataFrame.
      - Raise a ValueError if ``split_directions`` and no non-NaN
        direction ID values present.
  
      """
      if trip_subset.empty:
          return pd.DataFrame()
  
      f = pd.merge(stop_times_subset, trip_subset)
  
      # Convert departure times to seconds to ease headway calculations
      f["departure_time"] = f["departure_time"].map(hp.timestr_to_seconds)
  
      headway_start = hp.timestr_to_seconds(headway_start_time)
      headway_end = hp.timestr_to_seconds(headway_end_time)
  
      # Compute stats for each stop
      def compute_stop_stats(group):
          # Operate on the group of all stop times for an individual stop
          d = OrderedDict()
          d["num_routes"] = group["route_id"].unique().size
          d["num_trips"] = group.shape[0]
          d["start_time"] = group["departure_time"].min()
          d["end_time"] = group["departure_time"].max()
          headways = []
          dtimes = sorted(
              [
                  dtime
                  for dtime in group["departure_time"].values
                  if headway_start <= dtime <= headway_end
              ]
          )
          headways.extend(
              [dtimes[i + 1] - dtimes[i] for i in range(len(dtimes) - 1)]
          )
          if headways:
              d["max_headway"] = np.max(headways) / 60  # minutes
              d["min_headway"] = np.min(headways) / 60  # minutes
              d["mean_headway"] = np.mean(headways) / 60  # minutes
          else:
              d["max_headway"] = np.nan
              d["min_headway"] = np.nan
              d["mean_headway"] = np.nan
          return pd.Series(d)
  
      if split_directions:
          if "direction_id" not in f.columns:
              f["direction_id"] = np.nan
          f = f.loc[lambda x: x.direction_id.notnull()].assign(
              direction_id=lambda x: x.direction_id.astype(int)
          )
          if f.empty:
              raise ValueError(
                  "At least one trip direction ID value " "must be non-NaN."
              )
          g = f.groupby(["stop_id", "direction_id"])
      else:
          g = f.groupby("stop_id")
  
      result = g.apply(compute_stop_stats).reset_index()
  
      # Convert start and end times to time strings
      result[["start_time", "end_time"]] = result[
          ["start_time", "end_time"]
      ].applymap(lambda x: hp.timestr_to_seconds(x, inverse=True))
  
      return result