code: def _compute_predicates(table_op, predicates, data, scope, **kwargs):
      
      for predicate in predicates:
          # Map each root table of the predicate to the data so that we compute
          # predicates on the result instead of any left or right tables if the
          # Selection is on a Join. Project data to only inlude columns from
          # the root table.
          root_tables = predicate.op().root_tables()
  
          # handle suffixes
          additional_scope = {}
          data_columns = frozenset(data.columns)
  
          for root_table in root_tables:
              mapping = remap_overlapping_column_names(
                  table_op, root_table, data_columns
              )
              if mapping is not None:
                  new_data = data.loc[:, mapping.keys()].rename(columns=mapping)
              else:
                  new_data = data
              additional_scope[root_table] = new_data
  
          new_scope = toolz.merge(scope, additional_scope)
          yield execute(predicate, scope=new_scope, **kwargs)
docs: Compute the predicates for a table operation.
  
      Parameters
      ----------
      table_op : TableNode
      predicates : List[ir.ColumnExpr]
      data : pd.DataFrame
      scope : dict
      kwargs : dict
  
      Returns
      -------
      computed_predicate : pd.Series[bool]
  
      Notes
      -----
      This handles the cases where the predicates are computed columns, in
      addition to the simple case of named columns coming directly from the input
      table.