class_docstr: An abstract pipeline loader for estimates data that can load data a
  variable number of quarters forwards/backwards from calendar dates
  depending on the `num_announcements` attribute of the columns' dataset.
  If split adjustments are to be applied, a loader, split-adjusted columns,
  and the split-adjusted asof-date must be supplied.
  
  Parameters
  ----------
  estimates : pd.DataFrame
      The raw estimates data.
      ``estimates`` must contain at least 5 columns:
          sid : int64
              The asset id associated with each estimate.
  
          event_date : datetime64[ns]
              The date on which the event that the estimate is for will/has
              occurred..
  
          timestamp : datetime64[ns]
              The date on which we learned about the estimate.
  
          fiscal_quarter : int64
              The quarter during which the event has/will occur.
  
          fiscal_year : int64
              The year during which the event has/will occur.
  
  name_map : dict[str -> str]
      A map of names of BoundColumns that this loader will load to the
      names of the corresponding columns in `events`.
class_docstr_tok: ["An","abstract","pipeline","loader","for","estimates","data","that","can","load","data","a","variable","number","of","quarters","forwards\/backwards","from","calendar","dates","depending","on","the","`","num_announcements","`","attribute","of","the","columns","'","dataset",".","If","split","adjustments","are","to","be","applied",",","a","loader",",","split-adjusted","columns",",","and","the","split-adjusted","asof-date","must","be","supplied",".","Parameters","--","--","--","--","--","estimates",":","pd.DataFrame","The","raw","estimates","data",".","``","estimates","``","must","contain","at","least","5","columns",":","sid",":","int64","The","asset","id","associated","with","each","estimate",".","event_date",":","datetime64","[","ns","]","The","date","on","which","the","event","that","the","estimate","is","for","will\/has","occurred","..","timestamp",":","datetime64","[","ns","]","The","date","on","which","we","learned","about","the","estimate",".","fiscal_quarter",":","int64","The","quarter","during","which","the","event","has\/will","occur",".","fiscal_year",":","int64","The","year","during","which","the","event","has\/will","occur",".","name_map",":","dict","[","str","-",">","str","]","A","map","of","names","of","BoundColumns","that","this","loader","will","load","to","the","names","of","the","corresponding","columns","in","`","events","`","."]
docstr: Determine the last piece of information we know for each column on each
  date in the index for each sid and quarter.
  
  Parameters
  ----------
  assets_with_data : pd.Index
      Index of all assets that appear in the raw data given to the
      loader.
  columns : iterable of BoundColumn
      The columns that need to be loaded from the raw data.
  dates : pd.DatetimeIndex
      The calendar of dates for which data should be loaded.
  
  Returns
  -------
  stacked_last_per_qtr : pd.DataFrame
      A DataFrame indexed by [dates, sid, normalized_quarters] that has
      the latest information for each row of the index, sorted by event
      date.
  last_per_qtr : pd.DataFrame
      A DataFrame with columns that are a MultiIndex of [
      self.estimates.columns, normalized_quarters, sid].
docstr_tok: ["Determine","the","last","piece","of","information","we","know","for","each","column","on","each","date","in","the","index","for","each","sid","and","quarter",".","Parameters","--","--","--","--","--","assets_with_data",":","pd.Index","Index","of","all","assets","that","appear","in","the","raw","data","given","to","the","loader",".","columns",":","iterable","of","BoundColumn","The","columns","that","need","to","be","loaded","from","the","raw","data",".","dates",":","pd.DatetimeIndex","The","calendar","of","dates","for","which","data","should","be","loaded",".","Returns","--","--","--","-","stacked_last_per_qtr",":","pd.DataFrame","A","DataFrame","indexed","by","[","dates",",","sid",",","normalized_quarters","]","that","has","the","latest","information","for","each","row","of","the","index",",","sorted","by","event","date",".","last_per_qtr",":","pd.DataFrame","A","DataFrame","with","columns","that","are","a","MultiIndex","of","[","self.estimates.columns",",","normalized_quarters",",","sid","]","."]
code: def get_last_data_per_qtr(self, assets_with_data, columns, dates):
      """
      Determine the last piece of information we know for each column on each
      date in the index for each sid and quarter.
  
      Parameters
      ----------
      assets_with_data : pd.Index
          Index of all assets that appear in the raw data given to the
          loader.
      columns : iterable of BoundColumn
          The columns that need to be loaded from the raw data.
      dates : pd.DatetimeIndex
          The calendar of dates for which data should be loaded.
  
      Returns
      -------
      stacked_last_per_qtr : pd.DataFrame
          A DataFrame indexed by [dates, sid, normalized_quarters] that has
          the latest information for each row of the index, sorted by event
          date.
      last_per_qtr : pd.DataFrame
          A DataFrame with columns that are a MultiIndex of [
          self.estimates.columns, normalized_quarters, sid].
      """
      # Get a DataFrame indexed by date with a MultiIndex of columns of [
      # self.estimates.columns, normalized_quarters, sid], where each cell
      # contains the latest data for that day.
      last_per_qtr = last_in_date_group(
          self.estimates,
          dates,
          assets_with_data,
          reindex=True,
          extra_groupers=[NORMALIZED_QUARTERS],
      )
      # Forward fill values for each quarter/sid/dataset column.
      ffill_across_cols(last_per_qtr, columns, self.name_map)
      # Stack quarter and sid into the index.
      stacked_last_per_qtr = last_per_qtr.stack(
          [SID_FIELD_NAME, NORMALIZED_QUARTERS],
      )
      # Set date index name for ease of reference
      stacked_last_per_qtr.index.set_names(
          SIMULATION_DATES,
          level=0,
          inplace=True,
      )
      stacked_last_per_qtr = stacked_last_per_qtr.sort_values(
          EVENT_DATE_FIELD_NAME,
      )
      stacked_last_per_qtr[EVENT_DATE_FIELD_NAME] = pd.to_datetime(
          stacked_last_per_qtr[EVENT_DATE_FIELD_NAME]
      )
      return last_per_qtr, stacked_last_per_qtr
  
imports: from abc import abstractmethod, abstractproperty
  import numpy
  import pandas
  from six import viewvalues
  from toolz import groupby
  from catalyst.lib.adjusted_array import AdjustedArray
  from catalyst.lib.adjustment import Datetime641DArrayOverwrite, Datetime64Overwrite, Float641DArrayOverwrite, Float64Multiply, Float64Overwrite
  from catalyst.pipeline.common import EVENT_DATE_FIELD_NAME, FISCAL_QUARTER_FIELD_NAME, FISCAL_YEAR_FIELD_NAME, SID_FIELD_NAME, TS_FIELD_NAME
  from catalyst.pipeline.loaders.base import PipelineLoader
  from catalyst.utils.numpy_utils import datetime64ns_dtype, float64_dtype
  from catalyst.pipeline.loaders.utils import ffill_across_cols, last_in_date_group
label_desc: Use image node_id 16 for calling the EarningsEstimatesLoader obj's underlying member method code with example usage: obj.get_last_data_per_qtr(assets_with_data, columns, dates) and returns: last_per_qtr,  stacked_last_per_qtr