nodes: 0, module; 1, function_definition; 2, function_name:build_stop_timetable; 3, parameters; 4, type; 5, block; 6, typed_parameter; 7, typed_parameter; 8, typed_parameter; 9, identifier:DataFrame; 10, expression_statement; 11, expression_statement; 12, if_statement; 13, expression_statement; 14, expression_statement; 15, expression_statement; 16, expression_statement; 17, for_statement; 18, expression_statement; 19, return_statement; 20, identifier:feed; 21, type; 22, identifier:stop_id; 23, type; 24, identifier:dates; 25, type; 26, comment:"""
      Return a DataFrame containing the timetable for the given stop ID
      and dates.
  
      Parameters
      ----------
      feed : Feed
      stop_id : string
          ID of the stop for which to build the timetable
      dates : string or list
          A YYYYMMDD date string or list thereof
  
      Returns
      -------
      DataFrame
          The columns are all those in ``feed.trips`` plus those in
          ``feed.stop_times`` plus ``'date'``, and the stop IDs are
          restricted to the given stop ID.
          The result is sorted by date then departure time.
  
      Notes
      -----
      Assume the following feed attributes are not ``None``:
  
      - ``feed.trips``
      - Those used in :func:`.stop_times.get_stop_times`
  
      """; 27, assignment; 28, not_operator; 29, block; 30, assignment; 31, assignment; 32, assignment; 33, assignment; 34, identifier:date; 35, identifier:dates; 36, comment:# Slice to stops active on date; 37, block; 38, assignment; 39, call; 40, string:"Feed"; 41, identifier:str; 42, generic_type; 43, identifier:dates; 44, call; 45, identifier:dates; 46, return_statement; 47, identifier:t; 48, call; 49, identifier:t; 50, call; 51, identifier:a; 52, call; 53, identifier:frames; 54, list; 55, expression_statement; 56, expression_statement; 57, expression_statement; 58, expression_statement; 59, identifier:f; 60, call; 61, attribute; 62, argument_list; 63, identifier:List; 64, type_parameter; 65, attribute; 66, argument_list; 67, call; 68, attribute; 69, argument_list; 70, attribute; 71, argument_list; 72, attribute; 73, argument_list; 74, assignment; 75, assignment; 76, assignment; 77, call; 78, attribute; 79, argument_list; 80, identifier:f; 81, identifier:sort_values; 82, list; 83, type; 84, identifier:feed; 85, identifier:restrict_dates; 86, identifier:dates; 87, attribute; 88, argument_list; 89, identifier:pd; 90, identifier:merge; 91, attribute; 92, attribute; 93, subscript; 94, identifier:copy; 95, identifier:feed; 96, identifier:compute_trip_activity; 97, identifier:dates; 98, identifier:ids; 99, subscript; 100, identifier:f; 101, call; 102, subscript; 103, identifier:date; 104, attribute; 105, argument_list; 106, identifier:pd; 107, identifier:concat; 108, identifier:frames; 109, string:"date"; 110, string:"departure_time"; 111, identifier:str; 112, identifier:pd; 113, identifier:DataFrame; 114, identifier:feed; 115, identifier:trips; 116, identifier:feed; 117, identifier:stop_times; 118, identifier:t; 119, comparison_operator:t["stop_id"] == stop_id; 120, attribute; 121, comparison_operator:a[date] == 1; 122, string:"trip_id"; 123, attribute; 124, argument_list; 125, identifier:f; 126, string:"date"; 127, identifier:frames; 128, identifier:append; 129, identifier:f; 130, subscript; 131, identifier:stop_id; 132, identifier:a; 133, identifier:loc; 134, subscript; 135, integer:1; 136, subscript; 137, identifier:copy; 138, identifier:t; 139, string:"stop_id"; 140, identifier:a; 141, identifier:date; 142, identifier:t; 143, call; 144, attribute; 145, argument_list; 146, subscript; 147, identifier:isin; 148, identifier:ids; 149, identifier:t; 150, string:"trip_id"
code: def build_stop_timetable(
      feed: "Feed", stop_id: str, dates: List[str]
  ) -> DataFrame:
      """
      Return a DataFrame containing the timetable for the given stop ID
      and dates.
  
      Parameters
      ----------
      feed : Feed
      stop_id : string
          ID of the stop for which to build the timetable
      dates : string or list
          A YYYYMMDD date string or list thereof
  
      Returns
      -------
      DataFrame
          The columns are all those in ``feed.trips`` plus those in
          ``feed.stop_times`` plus ``'date'``, and the stop IDs are
          restricted to the given stop ID.
          The result is sorted by date then departure time.
  
      Notes
      -----
      Assume the following feed attributes are not ``None``:
  
      - ``feed.trips``
      - Those used in :func:`.stop_times.get_stop_times`
  
      """
      dates = feed.restrict_dates(dates)
      if not dates:
          return pd.DataFrame()
  
      t = pd.merge(feed.trips, feed.stop_times)
      t = t[t["stop_id"] == stop_id].copy()
      a = feed.compute_trip_activity(dates)
  
      frames = []
      for date in dates:
          # Slice to stops active on date
          ids = a.loc[a[date] == 1, "trip_id"]
          f = t[t["trip_id"].isin(ids)].copy()
          f["date"] = date
          frames.append(f)
  
      f = pd.concat(frames)
      return f.sort_values(["date", "departure_time"])