class_docstr: Estimate effect of treatment by finding matching treated and control
  units based on propensity score.
  
  Straightforward application of the back-door criterion.
  
  Supports additional parameters as listed below.
code: def estimate_effect(
      self,
      data: pd.DataFrame,
      treatment_value: Any = 1,
      control_value: Any = 0,
      target_units=None,
      **_,
  ):
      self._target_units = target_units
      self._treatment_value = treatment_value
      self._control_value = control_value
      if self.propensity_score_column not in data:
          self.estimate_propensity_score_column(data)
  
      # this assumes a binary treatment regime
      treated = data.loc[
          data[self._target_estimand.treatment_variable[0]] == 1
      ]
      control = data.loc[
          data[self._target_estimand.treatment_variable[0]] == 0
      ]
  
      # TODO remove neighbors that are more than a given radius apart
  
      # estimate ATT on treated by summing over difference between matched neighbors
      control_neighbors = NearestNeighbors(
          n_neighbors=1, algorithm="ball_tree"
      ).fit(control[self.propensity_score_column].values.reshape(-1, 1))
      distances, indices = control_neighbors.kneighbors(
          treated[self.propensity_score_column].values.reshape(-1, 1)
      )
      self.logger.debug("distances:")
      self.logger.debug(distances)
  
      att = 0
      numtreatedunits = treated.shape[0]
      for i in range(numtreatedunits):
          treated_outcome = treated.iloc[i][
              self._target_estimand.outcome_variable[0]
          ].item()
          control_outcome = control.iloc[indices[i]][
              self._target_estimand.outcome_variable[0]
          ].item()
          att += treated_outcome - control_outcome
  
      att /= numtreatedunits
  
      # Now computing ATC
      treated_neighbors = NearestNeighbors(
          n_neighbors=1, algorithm="ball_tree"
      ).fit(treated[self.propensity_score_column].values.reshape(-1, 1))
      distances, indices = treated_neighbors.kneighbors(
          control[self.propensity_score_column].values.reshape(-1, 1)
      )
      atc = 0
      numcontrolunits = control.shape[0]
      for i in range(numcontrolunits):
          control_outcome = control.iloc[i][
              self._target_estimand.outcome_variable[0]
          ].item()
          treated_outcome = treated.iloc[indices[i]][
              self._target_estimand.outcome_variable[0]
          ].item()
          atc += treated_outcome - control_outcome
  
      atc /= numcontrolunits
  
      if target_units == "att":
          est = att
      elif target_units == "atc":
          est = atc
      elif target_units == "ate":
          est = (att * numtreatedunits + atc * numcontrolunits) / (
              numtreatedunits + numcontrolunits
          )
      else:
          raise ValueError("Target units string value not supported")
  
      estimate = CausalEstimate(
          data=data,
          treatment_name=self._target_estimand.treatment_variable,
          outcome_name=self._target_estimand.outcome_variable,
          estimate=est,
          control_value=control_value,
          treatment_value=treatment_value,
          target_estimand=self._target_estimand,
          realized_estimand_expr=self.symbolic_estimator,
          propensity_scores=data[self.propensity_score_column],
      )
  
      estimate.add_estimator(self)
      return estimate
  
file_path: dowhy/dowhy/causal_estimators/propensity_score_matching_estimator.py
imports: from typing import Any, List, Optional, Union
  import pandas
  from sklearn.neighbors import NearestNeighbors
  from dowhy.causal_estimator import CausalEstimate, CausalEstimator
  from dowhy.causal_estimators.propensity_score_estimator import PropensityScoreEstimator
  from dowhy.causal_identifier import IdentifiedEstimand
label_desc: Use image node_id 3 for calling the PropensityScoreMatchingEstimator obj's underlying member method code with example usage: obj.estimate_effect(data, treatment_value, control_value, target_units) and returns: estimate