code: def hclust(
      X, y=None, linkage="single", metric="auto", random_state=0
  ):
      if isinstance(X, pd.DataFrame):
          X = X.values
  
      if metric == "auto":
          if y is not None:
              metric = "xgboost_distances_r2"
  
      # build the distance matrix
      if metric == "xgboost_distances_r2":
          dist_full = xgboost_distances_r2(
              X, y, random_state=random_state
          )
  
          # build a condensed upper triangular version by taking the max distance from either direction
          dist = []
          for i in range(dist_full.shape[0]):
              for j in range(i + 1, dist_full.shape[1]):
                  if i != j:
                      if linkage == "single":
                          dist.append(
                              min(dist_full[i, j], dist_full[j, i])
                          )
                      elif linkage == "complete":
                          dist.append(
                              max(dist_full[i, j], dist_full[j, i])
                          )
                      elif linkage == "average":
                          dist.append(
                              (dist_full[i, j] + dist_full[j, i]) / 2
                          )
                      else:
                          raise Exception("Unsupported linkage type!")
          dist = np.array(dist)
  
      else:
          if y is not None:
              warnings.warn(
                  "Ignoring the y argument passed to shap.utils.hclust since the given clustering metric is not based on label fitting!"
              )
          if isinstance(X, pd.DataFrame):
              bg_no_nan = X.values.copy()
          else:
              bg_no_nan = X.copy()
          for i in range(bg_no_nan.shape[1]):
              np.nan_to_num(
                  bg_no_nan[:, i],
                  nan=np.nanmean(bg_no_nan[:, i]),
                  copy=False,
              )
          dist = scipy.spatial.distance.pdist(
              bg_no_nan.T + np.random.randn(*bg_no_nan.T.shape) * 1e-8,
              metric=metric,
          )
      # else:
      #     raise Exception("Unknown metric: " + str(metric))
  
      # build linkage
      if linkage == "single":
          return scipy.cluster.hierarchy.single(dist)
      elif linkage == "complete":
          return scipy.cluster.hierarchy.complete(dist)
      elif linkage == "average":
          return scipy.cluster.hierarchy.average(dist)
      else:
          raise Exception("Unknown linkage: " + str(linkage))
  
file_path: shap/shap/utils/_clustering.py
imports: import warnings
  import numpy
  import pandas
  import scipy.cluster
  import scipy.spatial
  import sklearn
  from numba import njit
  from ._show_progress import show_progress
label_desc: Use image node_id 10 for calling a global function with example usage: hclust(X, y, linkage, metric, random_state) and returns: scipy, scipy, scipy