nodes: 0, module; 1, function_definition; 2, function_name:last_in_date_group; 3, parameters; 4, block; 5, identifier:df; 6, identifier:data_query_cutoff_times; 7, identifier:assets; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, expression_statement; 12, expression_statement; 13, if_statement; 14, if_statement; 15, expression_statement; 16, expression_statement; 17, comment:# For the number of things that we're grouping by (except TS), unstack; 18, comment:# the df. Done this way because of an unresolved pandas bug whereby; 19, comment:# passing a list of levels with mixed dtypes to unstack causes the; 20, comment:# resulting DataFrame to have all object-type columns.; 21, for_statement; 22, if_statement; 23, return_statement; 24, identifier:reindex; 25, True; 26, identifier:have_sids; 27, True; 28, identifier:extra_groupers; 29, None; 30, comment:"""
      Determine the last piece of information known on each date in the date
  
      index for each group. Input df MUST be sorted such that the correct last
      item is chosen from each group.
  
      Parameters
      ----------
      df : pd.DataFrame
          The DataFrame containing the data to be grouped. Must be sorted so that
          the correct last item is chosen from each group.
      data_query_cutoff_times : pd.DatetimeIndex
          The dates to use for grouping and reindexing.
      assets : pd.Int64Index
          The assets that should be included in the column multiindex.
      reindex : bool
          Whether or not the DataFrame should be reindexed against the date
          index. This will add back any dates to the index that were grouped
          away.
      have_sids : bool
          Whether or not the DataFrame has sids. If it does, they will be used
          in the groupby.
      extra_groupers : list of str
          Any extra field names that should be included in the groupby.
  
      Returns
      -------
      last_in_group : pd.DataFrame
          A DataFrame with dates as the index and fields used in the groupby as
          levels of a multiindex of columns.
  
      """; 31, assignment; 32, identifier:have_sids; 33, block; 34, comparison_operator:extra_groupers is None; 35, block; 36, augmented_assignment; 37, assignment; 38, identifier:_; 39, call; 40, block; 41, identifier:reindex; 42, block; 43, identifier:last_in_group; 44, identifier:idx; 45, list; 46, expression_statement; 47, identifier:extra_groupers; 48, None; 49, expression_statement; 50, identifier:idx; 51, identifier:extra_groupers; 52, identifier:last_in_group; 53, call; 54, identifier:range; 55, argument_list; 56, expression_statement; 57, if_statement; 58, subscript; 59, augmented_assignment; 60, assignment; 61, attribute; 62, argument_list; 63, binary_operator:len(idx) - 1; 64, assignment; 65, identifier:have_sids; 66, block; 67, else_clause; 68, identifier:data_query_cutoff_times; 69, call; 70, identifier:idx; 71, list; 72, identifier:extra_groupers; 73, list; 74, call; 75, identifier:last; 76, call; 77, integer:1; 78, identifier:last_in_group; 79, call; 80, expression_statement; 81, expression_statement; 82, block; 83, attribute; 84, argument_list; 85, identifier:SID_FIELD_NAME; 86, attribute; 87, argument_list; 88, identifier:len; 89, argument_list; 90, attribute; 91, argument_list; 92, assignment; 93, assignment; 94, expression_statement; 95, identifier:data_query_cutoff_times; 96, identifier:searchsorted; 97, attribute; 98, call; 99, identifier:groupby; 100, identifier:idx; 101, keyword_argument; 102, identifier:idx; 103, identifier:last_in_group; 104, identifier:unstack; 105, unary_operator; 106, identifier:cols; 107, attribute; 108, identifier:last_in_group; 109, call; 110, assignment; 111, subscript; 112, identifier:values; 113, attribute; 114, argument_list; 115, identifier:sort; 116, False; 117, integer:1; 118, identifier:last_in_group; 119, identifier:columns; 120, attribute; 121, argument_list; 122, identifier:last_in_group; 123, call; 124, identifier:df; 125, identifier:TS_FIELD_NAME; 126, identifier:df; 127, identifier:drop; 128, identifier:TS_FIELD_NAME; 129, keyword_argument; 130, identifier:last_in_group; 131, identifier:reindex; 132, keyword_argument; 133, keyword_argument; 134, attribute; 135, argument_list; 136, identifier:axis; 137, integer:1; 138, identifier:index; 139, identifier:data_query_cutoff_times; 140, identifier:columns; 141, call; 142, identifier:last_in_group; 143, identifier:reindex; 144, identifier:data_query_cutoff_times; 145, attribute; 146, argument_list; 147, attribute; 148, identifier:from_product; 149, binary_operator:tuple(cols.levels[0:len(extra_groupers) + 1]) + (assets,); 150, keyword_argument; 151, identifier:pd; 152, identifier:MultiIndex; 153, call; 154, tuple; 155, identifier:names; 156, attribute; 157, identifier:tuple; 158, argument_list; 159, identifier:assets; 160, identifier:cols; 161, identifier:names; 162, subscript; 163, attribute; 164, slice; 165, identifier:cols; 166, identifier:levels; 167, integer:0; 168, binary_operator:len(extra_groupers) + 1; 169, call; 170, integer:1; 171, identifier:len; 172, argument_list; 173, identifier:extra_groupers
code: def last_in_date_group(df,
                         data_query_cutoff_times,
                         assets,
                         reindex=True,
                         have_sids=True,
                         extra_groupers=None):
      """
      Determine the last piece of information known on each date in the date
  
      index for each group. Input df MUST be sorted such that the correct last
      item is chosen from each group.
  
      Parameters
      ----------
      df : pd.DataFrame
          The DataFrame containing the data to be grouped. Must be sorted so that
          the correct last item is chosen from each group.
      data_query_cutoff_times : pd.DatetimeIndex
          The dates to use for grouping and reindexing.
      assets : pd.Int64Index
          The assets that should be included in the column multiindex.
      reindex : bool
          Whether or not the DataFrame should be reindexed against the date
          index. This will add back any dates to the index that were grouped
          away.
      have_sids : bool
          Whether or not the DataFrame has sids. If it does, they will be used
          in the groupby.
      extra_groupers : list of str
          Any extra field names that should be included in the groupby.
  
      Returns
      -------
      last_in_group : pd.DataFrame
          A DataFrame with dates as the index and fields used in the groupby as
          levels of a multiindex of columns.
  
      """
      idx = [data_query_cutoff_times[data_query_cutoff_times.searchsorted(
          df[TS_FIELD_NAME].values,
      )]]
      if have_sids:
          idx += [SID_FIELD_NAME]
      if extra_groupers is None:
          extra_groupers = []
      idx += extra_groupers
  
      last_in_group = df.drop(TS_FIELD_NAME, axis=1).groupby(
          idx,
          sort=False,
      ).last()
  
      # For the number of things that we're grouping by (except TS), unstack
      # the df. Done this way because of an unresolved pandas bug whereby
      # passing a list of levels with mixed dtypes to unstack causes the
      # resulting DataFrame to have all object-type columns.
      for _ in range(len(idx) - 1):
          last_in_group = last_in_group.unstack(-1)
  
      if reindex:
          if have_sids:
              cols = last_in_group.columns
              last_in_group = last_in_group.reindex(
                  index=data_query_cutoff_times,
                  columns=pd.MultiIndex.from_product(
                      tuple(cols.levels[0:len(extra_groupers) + 1]) + (assets,),
                      names=cols.names,
                  ),
              )
          else:
              last_in_group = last_in_group.reindex(data_query_cutoff_times)
  
      return last_in_group