code: def kappa(
      y_true: np.ndarray,
      y_pred: np.ndarray,
      weights: Optional[Union[str, np.ndarray]] = None,
      allow_off_by_one: bool = False,
  ) -> float:
      """
      Calculate the kappa inter-rater agreement.
  
      The agreement is calculated between the gold standard and the predicted
      ratings. Potential values range from -1 (representing complete disagreement)
      to 1 (representing complete agreement).  A kappa value of 0 is expected if
      all agreement is due to chance.
  
      In the course of calculating kappa, all items in ``y_true`` and ``y_pred`` will
      first be converted to floats and then rounded to integers.
  
      It is assumed that y_true and y_pred contain the complete range of possible
      ratings.
  
      This function contains a combination of code from yorchopolis's kappa-stats
      and Ben Hamner's Metrics projects on Github.
  
      Parameters
      ----------
      y_true : numpy.ndarray
          The true/actual/gold labels for the data.
      y_pred : numpy.ndarray
          The predicted/observed labels for the data.
      weights : Optional[Union[str, numpy.ndarray]], default=None
          Specifies the weight matrix for the calculation.
          Possible values are: ``None`` (unweighted-kappa), ``"quadratic"``
          (quadratically weighted kappa), ``"linear"`` (linearly weighted kappa),
          and a two-dimensional numpy array (a custom matrix of weights). Each
          weight in this array corresponds to the :math:`w_{ij}` values in the
          Wikipedia description of how to calculate weighted Cohen's kappa.
      allow_off_by_one : bool, default=False
          If true, ratings that are off by one are counted as
          equal, and all other differences are reduced by
          one. For example, 1 and 2 will be considered to be
          equal, whereas 1 and 3 will have a difference of 1
          for when building the weights matrix.
  
      Returns
      -------
      float
          The weighted or unweighted kappa score.
  
      Raises
      ------
      AssertionError
          If ``y_true`` != ``y_pred``.
      ValueError
          If labels cannot be converted to int.
      ValueError
          If invalid weight scheme.
      """
      # Ensure that the lists are both the same length
      assert len(y_true) == len(y_pred)
  
      # This rather crazy looking typecast is intended to work as follows:
      # If an input is an int, the operations will have no effect.
      # If it is a float, it will be rounded and then converted to an int
      # because the ml_metrics package requires ints.
      # If it is a str like "1", then it will be converted to a (rounded) int.
      # If it is a str that can't be typecast, then the user is
      # given a hopefully useful error message.
      try:
          y_true = np.array([int(np.round(float(y))) for y in y_true])
          y_pred = np.array([int(np.round(float(y))) for y in y_pred])
      except ValueError:
          raise ValueError(
              "For kappa, the labels should be integers or strings"
              " that can be converted to ints (E.g., '4.0' or "
              "'3')."
          )
  
      # Figure out normalized expected values
      min_rating = min(min(y_true), min(y_pred))
      max_rating = max(max(y_true), max(y_pred))
  
      # shift the values so that the lowest value is 0
      # (to support scales that include negative values)
      y_true = y_true - min_rating
      y_pred = y_pred - min_rating
  
      # Build the observed/confusion matrix
      num_ratings = max_rating - min_rating + 1
      observed = confusion_matrix(
          y_true, y_pred, labels=list(range(num_ratings))
      )
      num_scored_items = float(len(y_true))
  
      # Build weight array if weren't passed one
      if isinstance(weights, str):
          wt_scheme = weights
          weights = None
      else:
          wt_scheme = ""
  
      if weights is None:
          kappa_weights = np.empty((num_ratings, num_ratings))
          for i in range(num_ratings):
              for j in range(num_ratings):
                  diff = abs(i - j)
                  if allow_off_by_one and diff:
                      diff -= 1
                  if wt_scheme == "linear":
                      kappa_weights[i, j] = diff
                  elif wt_scheme == "quadratic":
                      kappa_weights[i, j] = diff**2
                  elif not wt_scheme:  # unweighted
                      kappa_weights[i, j] = bool(diff)
                  else:
                      raise ValueError(
                          "Invalid weight scheme specified for "
                          f"kappa: {wt_scheme}"
                      )
      else:
          kappa_weights = weights
  
      hist_true: np.ndarray = np.bincount(y_true, minlength=num_ratings)
      hist_true = hist_true[:num_ratings] / num_scored_items
      hist_pred: np.ndarray = np.bincount(y_pred, minlength=num_ratings)
      hist_pred = hist_pred[:num_ratings] / num_scored_items
      expected = np.outer(hist_true, hist_pred)
  
      # Normalize observed array
      observed = observed / num_scored_items
  
      # If all weights are zero, that means no disagreements matter.
      k = 1.0
      if np.count_nonzero(kappa_weights):
          observed_sum = np.sum(kappa_weights * observed)
          expected_sum = np.sum(kappa_weights * expected)
          k -= np.sum(observed_sum) / np.sum(expected_sum)
  
      return k
  
file_path: skll/skll/metrics.py
imports: import copy
  import sys
  from importlib import import_module
  from inspect import signature
  from pathlib import Path
  from typing import Optional, Union
  import numpy
  from scipy.stats import kendalltau, pearsonr, spearmanr
  from sklearn.metrics import confusion_matrix, f1_score, fbeta_score, get_scorer, get_scorer_names, make_scorer
  from skll.types import PathOrStr
label_desc: Use image node_id 1 for calling a global function with example usage: kappa(y_true, y_pred, weights, allow_off_by_one) and returns: k