Source code for pyagree.standard

"""This file contains the implementation of the standard agreement measures.

.. moduleauthor:: Alberto Casagrande <acasagrande@units.it>

"""

from math import sqrt

from numpy import multiply, matrix
from numpy import any as np_any

from .common import test_agreement_matrix


[docs]def bennett_s(agreement_matrix): r"""Evaluate Bennett, Alpert and Goldstein's :math:`S` Compute the :ref:`BennettS_theory` of agreement_matrix. :param agreement_matrix: An :math:`n \times n`-agreement matrix :type agreement_matrix: :class:`numpy.ndarray` :returns: The Bennett, Alpert and Goldstein's :math:`S` of agreement_matrix :rtype: :class:`float` :raises: :class:`ValueError` """ if isinstance(agreement_matrix, list): agreement_matrix = matrix(agreement_matrix) test_agreement_matrix(agreement_matrix) if agreement_matrix.shape[0] < 2: raise ValueError("The matrix has less than 2 rows and columns") k = agreement_matrix.shape[0] p_a = sum(agreement_matrix[i, i] for i in range(k))/agreement_matrix.sum() return (k*p_a-1)/(k-1)
[docs]def bangdiwala_b(agreement_matrix): r"""Evaluate Bangdiwala's :math:`B` Compute the :ref:`BangdiwalaB_theory` of agreement_matrix. :param agreement_matrix: An :math:`n \times n`-agreement matrix :type agreement_matrix: :class:`numpy.ndarray` :returns: The Bangdiwala's :math:`B` of agreement_matrix :rtype: :class:`float` :raises: :class:`ValueError` """ if isinstance(agreement_matrix, list): agreement_matrix = matrix(agreement_matrix) test_agreement_matrix(agreement_matrix) k = agreement_matrix.shape[0] p_a = sum(agreement_matrix[i, i]**2 for i in range(k)) p_e = sum(agreement_matrix[i, :].sum()*agreement_matrix[:, i].sum() for i in range(k)) if p_e == 0: raise ValueError("This matrix is out of the domain of Bangdiwala's B") return p_a/p_e
[docs]def cohen_kappa(agreement_matrix): r"""Evaluate Cohen's :math:`\kappa` Compute :ref:`CohenKappa_theory` of agreement_matrix. :param agreement_matrix: An :math:`n \times n`-agreement matrix :type agreement_matrix: :class:`numpy.ndarray` :returns: The Cohen's :math:`\kappa` of agreement_matrix :rtype: :class:`float` :raises: :class:`ValueError` """ if isinstance(agreement_matrix, list): agreement_matrix = matrix(agreement_matrix) test_agreement_matrix(agreement_matrix) k = agreement_matrix.shape[0] sum_am = agreement_matrix.sum() p_a = sum(agreement_matrix[i, i] for i in range(k))/sum_am p_e = sum(agreement_matrix[i, :].sum()*agreement_matrix[:, i].sum() for i in range(k))/(sum_am**2) if p_e == 1: raise ValueError("The agreement probability by chance of the " + "matrix is 1") return (p_a-p_e)/(1-p_e)
[docs]def scott_pi(agreement_matrix): r"""Evaluate Scott's :math:`\pi` Compute the :ref:`ScottPi_theory` of agreement_matrix. :param agreement_matrix: An :math:`n \times n`-agreement matrix :type agreement_matrix: :class:`numpy.ndarray` :returns: The Scott's :math:`\pi` of agreement_matrix :rtype: :class:`float` :raises: :class:`ValueError` """ if isinstance(agreement_matrix, list): agreement_matrix = matrix(agreement_matrix) test_agreement_matrix(agreement_matrix) sum_am2 = 2*agreement_matrix.sum() p_e = sum(((agreement_matrix[i, :].sum() + agreement_matrix[:, i].sum()) / sum_am2)**2 for i in range(agreement_matrix.shape[0])) p_a = 2*sum(agreement_matrix[i, i] for i in range(agreement_matrix.shape[0]))/sum_am2 if p_e == 1: raise ValueError("The sum of the squared joint proportions of " + "the matrix is 1") return (p_a-p_e)/(1-p_e)
[docs]def yule_y(agreement_matrix): r"""Evaluate Yule's :math:`Y` Compute the :ref:`YuleY_theory` of a :math:`2 \times 2`-agreement matrix agreement_matrix. :param agreement_matrix: A :math:`2 \times 2`-agreement matrix :type agreement_matrix: :class:`numpy.ndarray` :returns: The Yule :math:`Y` of agreement_matrix :rtype: :class:`float` :raises: :class:`ValueError` """ if isinstance(agreement_matrix, list): agreement_matrix = matrix(agreement_matrix) test_agreement_matrix(agreement_matrix) if agreement_matrix.shape[0] != 2: raise ValueError("The agreement matrix must be a 2x2-matrix") odd_r = 1 for i in range(agreement_matrix.shape[0]): for j in range(agreement_matrix.shape[1]): if i == j: odd_r *= agreement_matrix[i, j] else: if agreement_matrix[i, j] == 0: raise ValueError("Some elements outside the main " + "diagonal are 0") odd_r /= agreement_matrix[i, j] sqrt_odd_r = sqrt(odd_r) return (sqrt_odd_r-1)/(sqrt_odd_r+1)
[docs]def fleiss_kappa(classification_matrix): r"""Evaluate Fleiss's :math:`\kappa` Compute the :ref:`FleissKappa_theory` of a classification matrix classification_matrix. :param classification_matrix: An :math:`N \times k`-classification matrix :type classification_matrix: class:`numpy.ndarray` :returns: The Fleiss's :math:`\kappa` of classification_matrix :rtype: :class:`float` :raises: :class:`ValueError` """ if isinstance(classification_matrix, list): classification_matrix = matrix(classification_matrix) if np_any(classification_matrix < 0): raise ValueError("The matrix contains some negative values") dataset_size = classification_matrix.shape[0] num_of_classes = classification_matrix.shape[1] num_of_raters = classification_matrix[0, :].sum() d_n = dataset_size*num_of_raters p_0 = (multiply(classification_matrix, classification_matrix).sum()-d_n)/(d_n*(num_of_raters-1)) p_e = sum((classification_matrix[:, j].sum()/d_n)**2 for j in range(num_of_classes)) return (p_0-p_e)/(1-p_e)