Пример #1
0
def transposed_matrix(matrix):
    """
    Transpose a matrix's rows and columns

    Parameters
    ----------
    matrix : list of lists of int or float
        List of lists of numbers representing a matrix

    Raises
    ------
    TypeError
        Argument must be a 2-dimensional list
    TypeError
        Elements nested within argument must be integers or floats
    
    Returns
    -------
    matrix : list of lists of int or float
        List of lists in which each inner element occupies the row that correspond's to the column it occupied in the original matrix and the column that correspond's to the row it occupied in the original matrix

    See Also
    --------
    :func:`~regressions.matrices.cofactors.matrix_of_cofactors`, :func:`~regressions.matrices.minors.matrix_of_minors`, :func:`~regressions.matrices.determinant.linear_determinant`, :func:`~regressions.matrices.inverse.inverse_matrix`

    Notes
    -----
    - Original matrix: :math:`\\mathbf{A} = \\begin{bmatrix} a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\ a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \\end{bmatrix}`
    - Transpose of matrix: :math:`\\mathbf{A}^T = \\begin{bmatrix} a_{1,1} & a_{2,1} & \\cdots & a_{m,1} \\\\ a_{1,2} & a_{2,2} & \\cdots & a_{m,2} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ a_{1,n} & a_{2,n} & \\cdots & a_{m,n} \\end{bmatrix}`
    - |adjugate|

    Examples
    --------
    Import `transposed_matrix` function from `regressions` library
        >>> from regressions.matrices.transpose import transposed_matrix
    Transpose [[1, 2, 3], [4, 5, 6]]
        >>> matrix_3x2 = transposed_matrix([[1, 2, 3], [4, 5, 6]])
        >>> print(matrix_3x2)
        [[1, 4], [2, 5], [3, 6]]
    Transpose [[2, 3], [5, 7]]
        >>> matrix_2x2 = transposed_matrix([[2, 3], [5, 7]])
        >>> print(matrix_2x2)
        [[2, 5], [3, 7]]
    """
    # Handle input errors
    matrix_of_scalars(matrix)

    # Create list to return
    result = []

    # Iterate over inner lists of input
    for m in range(len(matrix[0])):
        # Create new lists inside list to return
        result.append([])

        # Iterate over outer lists of input
        for n in range(len(matrix)):
            # Store elements previously at inner-outer, now at outer-inner
            result[m].append(matrix[n][m])

    # Return result
    return result
Пример #2
0
def matrix_of_cofactors(matrix):
    """
    Create the matrix of cofactors corresponding to a given matrix

    Parameters
    ----------
    matrix : list of lists of int or float
        List of lists of numbers representing a matrix

    Raises
    ------
    TypeError
        Argument must be a 2-dimensional list
    TypeError
        Elements nested within argument must be integers or floats
    
    Returns
    -------
    matrix : list of lists of int or float
        List of lists in which each inner element alternates being positive or negative versions of the corresponding element from the original matrix

    See Also
    --------
    :func:`~regressions.matrices.minors.matrix_of_minors`, :func:`~regressions.matrices.transpose.transposed_matrix`, :func:`~regressions.matrices.determinant.linear_determinant`, :func:`~regressions.matrices.inverse.inverse_matrix`

    Notes
    -----
    - Original matrix: :math:`\\mathbf{A} = \\begin{bmatrix} a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\ a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \\end{bmatrix}`
    - Matrix of cofactors (if :math:`\\mathbf{A}` contains an odd number of rows and columns): :math:`\\mathbf{A}^C = \\begin{bmatrix} a_{1,1} & -1\\cdot{a_{1,2}} & \\cdots & a_{1,n} \\\\ -1\\cdot{a_{2,1}} & a_{2,2} & \\cdots & -1\\cdot{a_{2,n}} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ a_{m,1} & -1\\cdot{a_{m,2}} & \\cdots & a_{m,n} \\end{bmatrix}`
    - Matrix of cofactors (if :math:`\\mathbf{A}` contains an even number of rows and columns): :math:`\\mathbf{A}^C = \\begin{bmatrix} a_{1,1} & -1\\cdot{a_{1,2}} & \\cdots & -1\\cdot{a_{1,n}} \\\\ -1\\cdot{a_{2,1}} & a_{2,2} & \\cdots & a_{2,n} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ -1\\cdot{a_{m,1}} & a_{m,2} & \\cdots & a_{m,n} \\end{bmatrix}`
    - |cofactors|

    Examples
    --------
    Import `matrix_of_cofactors` function from `regressions` library
        >>> from regressions.matrices.cofactors import matrix_of_cofactors
    Create the matrix of cofactors for [[1, 2, 3], [4, 5, 6]]
        >>> matrix_3x2 = matrix_of_cofactors([[1, 2, 3], [4, 5, 6]])
        >>> print(matrix_3x2)
        [[1, -2, 3], [-4, 5, -6]]
    Create the matrix of cofactors for [[2, 3], [5, 7]]
        >>> matrix_2x2 = matrix_of_cofactors([[2, 3], [5, 7]])
        >>> print(matrix_2x2)
        [[2, -3], [-5, 7]]
    """
    # Handle input errors
    matrix_of_scalars(matrix)

    # Create list to return
    result = []

    # Iterate over outer lists of input
    for m in range(len(matrix)):
        # Create new lists inside list to return
        result.append([])

        if m % 2 == 0:
            # Iterate over inner lists of input
            for n in range(len(matrix[0])):
                # Handle even-even indexed elements
                if n % 2 == 0:
                    result[m].append(matrix[m][n])
                
                # Handle even-odd indexed elements
                else:
                    result[m].append(-1 * matrix[m][n])
        
        else:
            # Iterate over inner lists of input
            for n in range(len(matrix[0])):
                # Handle odd-even indexed elements
                if n % 2 == 0:
                    result[m].append(-1 * matrix[m][n])
                
                # Handle odd-odd indexed elements
                else:
                    result[m].append(matrix[m][n])
    
    # Return result
    return result
Пример #3
0
def linear_model(data, precision = 4):
    """
    Generates a linear regression model from a given data set

    Parameters
    ----------
    data : list of lists of int or float
        List of lists of numbers representing a collection of coordinate pairs; it must include at least 10 pairs
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    TypeError
        First argument must be a 2-dimensional list
    TypeError
        Elements nested within first argument must be integers or floats
    ValueError
        First argument must contain at least 10 elements
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    model['constants'] : list of float
        Coefficients of the resultant linear model; the first element is the coefficient of the linear term, and the second element is the coefficient of the constant term
    model['evaluations']['equation'] : func
        Function that evaluates the equation of the linear model at a given numeric input (e.g., model['evaluations']['equation'](10) would evaluate the equation of the linear model when the independent variable is 10)
    model['evaluations']['derivative'] : func
        Function that evaluates the first derivative of the linear model at a given numeric input (e.g., model['evaluations']['derivative'](10) would evaluate the first derivative of the linear model when the independent variable is 10)
    model['evaluations']['integral'] : func
        Function that evaluates the integral of the linear model at a given numeric input (e.g., model['evaluations']['integral'](10) would evaluate the integral of the linear model when the independent variable is 10)
    model['points']['roots'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the x-intercepts of the linear model (will contain exactly one point)
    model['points']['maxima'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the maxima of the linear model (will always be `None`)
    model['points']['minima'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the minima of the linear model (will always be `None`)
    model['points']['inflections'] : list of lists of float
        List of lists of numbers representing the coordinate pairs of all the inflection points of the linear model (will always be `None`)
    model['accumulations']['range'] : float
        Total area under the curve represented by the linear model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided (i.e., over the range)
    model['accumulations']['iqr'] : float
        Total area under the curve represented by the linear model between the first and third quartiles of all the independent coordinates originally provided (i.e., over the interquartile range)
    model['averages']['range']['average_value_derivative'] : float
        Average rate of change of the curve represented by the linear model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_derivative'] : list of float
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['range']['average_value_integral'] : float
        Average value of the curve represented by the linear model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_integral'] : list of float
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their value equals the function's average value over that interval
    model['averages']['iqr']['average_value_derivative'] : float
        Average rate of change of the curve represented by the linear model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_derivative'] : list of float
        All points between the first and third quartiles of all the independent coordinates originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['iqr']['average_value_integral'] : float
        Average value of the curve represented by the linear model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_integral'] : list of float
        All points between the first and third quartiles of all the independent coordinates originally provided where their value equals the function's average value over that interval
    model['correlation'] : float
        Correlation coefficient indicating how well the model fits the original data set (values range between 0.0, implying no fit, and 1.0, implying a perfect fit)

    See Also
    --------
    :func:`~regressions.analyses.equations.linear.linear_equation`, :func:`~regressions.analyses.derivatives.linear.linear_derivatives`, :func:`~regressions.analyses.integrals.linear.linear_integral`, :func:`~regressions.analyses.roots.linear.linear_roots`, :func:`~regressions.statistics.correlation.correlation_coefficient`, :func:`~regressions.execute.run_all`

    Notes
    -----
    - Provided ordered pairs for the data set: :math:`p_i = \\{ (p_{1,x}, p_{1,y}), (p_{2,x}, p_{2,y}), \\cdots, (p_{n,x}, p_{n,y}) \\}`
    - Provided values for the independent variable: :math:`X_i = \\{ p_{1,x}, p_{2,x}, \\cdots, p_{n,x} \\}`
    - Provided values for the dependent variable: :math:`Y_i = \\{ p_{1,y}, p_{2,y}, \\cdots, p_{n,y} \\}`
    - Minimum value of the provided values for the independent variable: :math:`X_{min} \\leq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - Maximum value of the provided values for the independent variable: :math:`X_{max} \\geq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - First quartile of the provided values for the independent variable: :math:`X_{Q1}`
    - Third quartile of the provided values for the independent variable: :math:`X_{Q3}`
    - Mean of all provided values for the dependent variable: :math:`\\bar{y} = \\frac{1}{n}\\cdot{\\sum\\limits_{i=1}^n Y_i}`
    - Resultant values for the coefficients of the linear model: :math:`C_i = \\{ a, b \\}`
    - Standard form for the equation of the linear model: :math:`f(x) = a\\cdot{x} + b`
    - First derivative of the linear model: :math:`f'(x) = a`
    - Second derivative of the linear model: :math:`f''(x) = 0`
    - Integral of the linear model: :math:`F(x) = \\frac{a}{2}\\cdot{x^2} + b\\cdot{x}`
    - Potential x-values of the roots of the linear model: :math:`x_{intercepts} = \\{ -\\frac{b}{a} \\}`
    - Potential x-values of the maxima of the linear model: :math:`x_{maxima} = \\{ \\varnothing \\}`
    - Potential x-values of the minima of the linear model: :math:`x_{minima} = \\{ \\varnothing \\}`
    - Potential x-values of the inflection points of the linear model: :math:`x_{inflections} = \\{ \\varnothing \\}`
    - Accumulatation of the linear model over its range: :math:`A_{range} = \\int_{X_{min}}^{X_{max}} f(x) \\,dx`
    - Accumulatation of the linear model over its interquartile range: :math:`A_{iqr} = \\int_{X_{Q1}}^{X_{Q3}} f(x) \\,dx`
    - Average rate of change of the linear model over its range: :math:`m_{range} = \\frac{f(X_{max}) - f(X_{min})}{X_{max} - X_{min}}`
    - Potential x-values at which the linear model's instantaneous rate of change equals its average rate of change over its range: :math:`x_{m,range} = \\{ [X_{min}, X_{max}] \\}`
    - Average value of the linear model over its range: :math:`v_{range} = \\frac{1}{X_{max} - X_{min}}\\cdot{A_{range}}`
    - Potential x-values at which the linear model's value equals its average value over its range: :math:`x_{v,range} = \\{ -\\frac{b - v_{range}}{a} \\}`
    - Average rate of change of the linear model over its interquartile range: :math:`m_{iqr} = \\frac{f(X_{Q3}) - f(X_{Q1})}{X_{Q3} - X_{Q1}}`
    - Potential x-values at which the linear model's instantaneous rate of change equals its average rate of change over its interquartile range: :math:`x_{m,iqr} = \\{ [X_{Q1}, X_{Q3}] \\}`
    - Average value of the linear model over its interquartile range: :math:`v_{iqr} = \\frac{1}{X_{Q3} - X_{Q1}}\\cdot{A_{iqr}}`
    - Potential x-values at which the linear model's value equals its average value over its interquartile range: :math:`x_{v,iqr} = \\{ -\\frac{b - v_{iqr}}{a} \\}`
    - Predicted values based on the linear model: :math:`\\hat{y}_i = \\{ \\hat{y}_1, \\hat{y}_2, \\cdots, \\hat{y}_n \\}`
    - Residuals of the dependent variable: :math:`e_i = \\{ p_{1,y} - \\hat{y}_1, p_{2,y} - \\hat{y}_2, \\cdots, p_{n,y} - \\hat{y}_n \\}`
    - Deviations of the dependent variable: :math:`d_i = \\{ p_{1,y} - \\bar{y}, p_{2,y} - \\bar{y}, \\cdots, p_{n,y} - \\bar{y} \\}`
    - Sum of squares of residuals: :math:`SS_{res} = \\sum\\limits_{i=1}^n e_i^2`
    - Sum of squares of deviations: :math:`SS_{dev} = \\sum\\limits_{i=1}^n d_i^2`
    - Correlation coefficient for the linear model: :math:`r = \\sqrt{1 - \\frac{SS_{res}}{SS_{dev}}}`
    - |regression_analysis|

    Examples
    --------
    Import `linear_model` function from `regressions` library
        >>> from regressions.models.linear import linear_model
    Generate a linear regression model for the data set [[1, 30], [2, 27], [3, 24], [4, 21], [5, 18], [6, 15], [7, 12], [8, 9], [9, 6], [10, 3]], then print its coefficients, roots, total accumulation over its interquartile range, and correlation
        >>> model_perfect = linear_model([[1, 30], [2, 27], [3, 24], [4, 21], [5, 18], [6, 15], [7, 12], [8, 9], [9, 6], [10, 3]])
        >>> print(model_perfect['constants'])
        [-3.0, 33.0]
        >>> print(model_perfect['points']['roots'])
        [[11.0, 0.0]]
        >>> print(model_perfect['accumulations']['iqr'])
        82.5
        >>> print(model_perfect['correlation'])
        1.0
    Generate a linear regression model for the data set [[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]], then print its coefficients, inflections, total accumulation over its range, and correlation
        >>> model_agnostic = linear_model([[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]])
        >>> print(model_agnostic['constants'])
        [1.9636, 23.0]
        >>> print(model_agnostic['points']['inflections'])
        [None]
        >>> print(model_agnostic['accumulations']['range'])
        304.1982
        >>> print(model_agnostic['correlation'])
        0.5516
    """
    # Handle input errors
    matrix_of_scalars(data, 'first')
    long_vector(data)
    positive_integer(precision)

    # Store independent and dependent variable values separately
    independent_variable = single_dimension(data, 1)
    dependent_variable = single_dimension(data, 2)

    # Create matrices for independent and dependent variables
    independent_matrix = []
    dependent_matrix = column_conversion(dependent_variable)

    # Iterate over inputted data
    for element in independent_variable:
        # Store linear and constant evaluations of original independent elements together as lists within independent matrix
        independent_matrix.append([element, 1])

    # Solve system of equations
    solution = system_solution(independent_matrix, dependent_matrix, precision)

    # Eliminate zeroes from solution
    coefficients = no_zeroes(solution, precision)

    # Generate evaluations for function, derivatives, and integral
    equation = linear_equation(*coefficients, precision)
    derivative = linear_derivatives(*coefficients, precision)['first']['evaluation']
    integral = linear_integral(*coefficients, precision)['evaluation']

    # Determine key points of graph
    points = key_coordinates('linear', coefficients, precision)

    # Generate values for lower and upper bounds
    five_numbers = five_number_summary(independent_variable, precision)
    min_value = five_numbers['minimum']
    max_value = five_numbers['maximum']
    q1 = five_numbers['q1']
    q3 = five_numbers['q3']

    # Calculate accumulations
    accumulated_range = accumulated_area('linear', coefficients, min_value, max_value, precision)
    accumulated_iqr = accumulated_area('linear', coefficients, q1, q3, precision)

    # Determine average values and their points
    averages_range = average_values('linear', coefficients, min_value, max_value, precision)
    averages_iqr = average_values('linear', coefficients, q1, q3, precision)

    # Create list of predicted outputs
    predicted = []
    for element in independent_variable:
        predicted.append(equation(element))
    
    # Calculate correlation coefficient for model
    accuracy = correlation_coefficient(dependent_variable, predicted, precision)

    # Package preceding results in multiple dictionaries
    evaluations = {
        'equation': equation,
        'derivative': derivative,
        'integral': integral
    }
    points = {
        'roots': points['roots'],
        'maxima': points['maxima'],
        'minima': points['minima'],
        'inflections': points['inflections']
    }
    accumulations = {
        'range': accumulated_range,
        'iqr': accumulated_iqr
    }
    averages = {
        'range': averages_range,
        'iqr': averages_iqr
    }

    # Package all dictionaries in single dictionary to return
    result = {
        'constants': coefficients,
        'evaluations': evaluations,
        'points': points,
        'accumulations': accumulations,
        'averages': averages,
        'correlation': accuracy
    }
    return result
def scalar_product_matrix(matrix, scalar):
    """
    Calculates the product of a matrix and a scalar

    Parameters
    ----------
    matrix : list of lists of int or float
        List of lists of numbers representing a matrix
    scalar : int or float
        Number representing a scalar

    Raises
    ------
    TypeError
        First argument must be 2-dimensional lists
    TypeError
        Elements nested within first argument must be integers or floats
    TypeError
        Second argument must be an integer or a float

    Returns
    -------
    matrix : list of lists of int or float
        List of lists in which each inner element is the product of the corresponding element from the input matrix and the scalar value

    See Also
    --------
    :func:`~regressions.vectors.multiplication.scalar_product_vector`, :func:`~regressions.matrices.addition.matrix_sum`

    Notes
    -----
    - Matrix: :math:`\\mathbf{A} = \\begin{bmatrix} a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\ a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \\end{bmatrix}`
    - Scalar: :math:`c`
    - Scalar product: :math:`c\\cdot{\\mathbf{A}} = \\begin{bmatrix} c\\cdot{a_{1,1}} & c\\cdot{a_{1,2}} & \\cdots & c\\cdot{a_{1,n}} \\\\ c\\cdot{a_{2,1}} & c\\cdot{a_{2,2}} & \\cdots & c\\cdot{a_{2,n}} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ c\\cdot{a_{m,1}} & c\\cdot{a_{m,2}} & \\cdots & c\\cdot{a_{m,n}} \\end{bmatrix}`
    - |matrix_scalar_multiplication|

    Examples
    --------
    Import `scalar_product_matrix` function from `regressions` library
        >>> from regressions.matrices.multiplication import scalar_product_matrix
    Multiply [[1, 2, 3], [4, 5, 6]] and -2
        >>> matrix_2x3 = scalar_product_matrix([[1, 2, 3], [4, 5, 6]], -2)
        >>> print(matrix_2x3)
        [[-2, -4, -6], [-8, -10, -12]]
    Multiply [[5, -7], [-3, 8]] and 3
        >>> matrix_2x2 = scalar_product_matrix([[5, -7], [-3, 8]], 3)
        >>> print(matrix_2x2)
        [[15, -21], [-9, 24]]
    """
    # Handle input errors
    matrix_of_scalars(matrix, 'first')
    scalar_value(scalar, 'second')

    # Create list to return
    result = []

    # Iterate over outer lists of input
    for m in range(len(matrix)):
        # Create new lists inside list to return
        result.append([])

        # Iterate over inner lists of input
        for n in range(len(matrix[0])):
            # Store products in inner lists of return
            result[m].append(matrix[m][n] * scalar)
    
    # Return result
    return result
Пример #5
0
def single_dimension(matrix, scalar = 1):
    """
    Extracts a column vector as a row vector from a matrix according to an integer corresponding to the column's position

    Parameters
    ----------
    matrix : list of lists of int or float
        List containing other lists, where each inner list is a row and elements within those inner lists correspond to columns
    scalar : int, default=1
        Number corresponding to the column's position

    Raises
    ------
    TypeError
        First argument must be a 2-dimensional list
    TypeError
        Elements nested within the first argument's lists must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    vector : list of int or float
        List containing only integers or floats

    See Also
    --------
    :func:`~regressions.vectors.column.column_conversion`, :func:`~regressions.statistics.sort.sorted_dimension`, :func:`~regressions.statistics.half.half_dimension`

    Notes
    -----
    - Matrix: :math:`\\begin{bmatrix} a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\ a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\ \\cdots & \\cdots & \\cdots & \\cdots \\\\ a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \\end{bmatrix}`
    - Row vector corresponding to the :math:`n`\ th column of the matrix: :math:`\\langle a_{1,n}, a_{2,n}, \\cdots, a_{m,n} \\rangle`

    Examples
    --------
    Import `single_dimension` function from `regressions` library
        >>> from regressions.vectors.dimension import single_dimension
    Extract the second column from the matrix [[3, 5, 9], [1, -4, 2]]
        >>> vector_2c = single_dimension([[3, 5, 9], [1, -4, 2]], 2)
        >>> print(vector_2c)
        [5, -4]
    Extract the first column from the matrix [[3, 5, 9], [1, -4, 2]]
        >>> vector_1c = single_dimension([[3, 5, 9], [1, -4, 2]], 1)
        >>> print(vector_1c)
        [3, 1]
    """
    # Handle input errors
    matrix_of_scalars(matrix, 'first')
    positive_integer(scalar)
    level(matrix, scalar)

    # Create list to return
    result = []

    # Iterate over input
    for element in matrix:
        # Store all elements at given dimension in list to return
        result.append(element[scalar - 1])
    
    # Return result
    return result
Пример #6
0
def half_dimension(data, dimension=1):
    """
    Splits an unsorted 2-dimensional data set into two sorted 2-dimensional data sets, each containing the same amount of elements, in which the sorting occurs based on the elements of the nested lists indicated by the dimension parameter (in sets with an odd amount of elements, the median is not included in either half)

    Parameters
    ----------
    data : list of lists of int or float
        List of lists of numbers to analyze
    dimension : int, default=1
        Number indicating by which element of the nested lists to sort
    
    Raises
    ------
    TypeError
        First argument must be a 2-dimensional list
    TypeError
        Elements nested within first argument must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    sections['upper'] : list of lists of int or float
        List of all elements from the upper half of a data set, sorted according to the elements occupying a provided position
    sections['lower'] : list of lists of int or float
        List of all elements from the lower half of a data set, sorted according to the elements occupying a provided position

    See Also
    --------
    :func:`~regressions.statistics.sort.sorted_dimension`, :func:`~regressions.vectors.dimension.single_dimension`

    Notes
    -----
    - Set of ordered pairs of numbers: :math:`a_i = \\{ ( a_{1,1}, a_{1,2}, \\cdots, a_{1,j}, a_{1,n} ), ( a_{2,1}, a_{2,2}, \\cdots, a_{2,j}, a_{2,n} ), \\cdots, \\\\ ( a_{m,1}, a_{m,2}, \\cdots, a_{m,j}, a_{m,n} ) \\}`
    - Sorted version of set according to the values in the :math:`j`\ th position: :math:`A_i = ( ( A_{1,1}, A_{1,2}, \\cdots, A_{1,j}, A_{1,n} ), ( A_{2,1}, A_{2,2}, \\cdots, A_{2,j}, A_{2,n} ), \\cdots, \\\\ ( A_{m,1}, A_{m,2}, \\cdots, A_{m,j}, A_{m,n} ) )`

        - For all terms in :math:`A_i`: :math:`A_{n-1,j} \\leq A_{n,j}`
    
    - For sets with an odd amount of ordered pairs:

        - Lower section: :math:`A_{lower} = ( ( A_{1,1}, A_{1,2}, \\cdots, A_{1,j}, A_{1,n} ), ( A_{2,1}, A_{2,2}, \\cdots, A_{2,j}, A_{2,n} ), \\cdots, \\\\ ( A_{\\lfloor m/2 \\rfloor,1}, A_{\\lfloor m/2 \\rfloor,2}, \\cdots, A_{\\lfloor m/2 \\rfloor,j}, A_{\\lfloor m/2 \\rfloor,n} ) )`
        - Upper section: :math:`A_{upper} = ( ( A_{\\lceil m/2 \\rceil,1}, A_{\\lceil m/2 \\rceil,2}, \\cdots, A_{\\lceil m/2 \\rceil,j}, A_{\\lceil m/2 \\rceil,n} ), ( A_{\\lceil m/2 \\rceil + 1,1}, A_{\\lceil m/2 \\rceil + 1,2}, \\cdots, \\\\ A_{\\lceil m/2 \\rceil + 1,j}, A_{\\lceil m/2 \\rceil + 1,n} ), \\cdots, ( A_{m,1}, A_{m,2}, \\cdots, A_{m,j}, A_{m,n} ) )`
    
    - For sets with an even amount of ordered pairs:

        - Lower section: :math:`A_{lower} = ( ( A_{1,1}, A_{1,2}, \\cdots, A_{1,j}, A_{1,n} ), ( A_{2,1}, A_{2,2}, \\cdots, A_{2,j}, A_{2,n} ), \\cdots, \\\\ ( A_{m/2,1}, A_{m/2,2}, \\cdots, A_{m/2,j}, A_{m/2,n} ) )`
        - Upper section: :math:`A_{upper} = ( ( A_{m/2 + 1,1}, A_{m/2 + 1,2}, \\cdots, A_{m/2 + 1,j}, A_{m/2 + 1,n} ), ( A_{m/2 + 2,1}, A_{m/2 + 2,2}, \\cdots, \\\\ A_{m/2 + 2,j}, A_{m/2 + 2,n} ), \\cdots, ( A_{m,1}, A_{m,2}, \\cdots, A_{m,j}, A_{m,n} ) )`

    Examples
    --------
    Import `half_dimension` function from `regressions` library
        >>> from regressions.statistics.halve import half_dimension
    Determine the upper half of the set [[3, 7, 1], [1, 8, 11], [6, 6, 6], [2, 15, 3], [10, 5, 9]] based on the second dimension
        >>> sections_2d = half_dimension([[3, 7, 1], [1, 8, 11], [6, 6, 6], [2, 15, 3], [10, 5, 9]], 2)
        >>> print(sections_2d['upper'])
        [[1, 8, 11], [2, 15, 3]]
    Determine the lower half of the set [[3, 7, 1], [1, 8, 11], [6, 6, 6], [2, 15, 3], [10, 5, 9]] based on the third dimension
        >>> sections_3d = half_dimension([[3, 7, 1], [1, 8, 11], [6, 6, 6], [2, 15, 3], [10, 5, 9]], 3)
        >>> print(sections_3d['lower'])
        [[3, 7, 1], [2, 15, 3]]
    """
    # Handle input errors
    matrix_of_scalars(data, 'first')
    positive_integer(dimension)

    # Sort input according to a provided dimension
    sorted_data = sorted_dimension(data, dimension)

    # Partition sorted input
    result = partition(sorted_data)
    return result
Пример #7
0
 def test_matrix_scalars_last_not_vector_raises(self):
     with self.assertRaises(Exception) as context:
         matrix_of_scalars(bad_matrix_last_not_vector)
     self.assertEqual(type(context.exception), TypeError)
     self.assertEqual(str(context.exception),
                      'Elements within argument must be lists')
Пример #8
0
 def test_matrix_scalars_2x2(self):
     matrix_scalars_2x2 = matrix_of_scalars(small_square)
     self.assertEqual(
         matrix_scalars_2x2,
         'Argument is a 2-dimensional list containing nested elements that are integers or floats'
     )
Пример #9
0
 def test_matrix_scalars_2x3(self):
     matrix_scalars_2x3 = matrix_of_scalars(first_matrix)
     self.assertEqual(
         matrix_scalars_2x3,
         'Argument is a 2-dimensional list containing nested elements that are integers or floats'
     )
Пример #10
0
def sinusoidal_model(data, precision=4):
    """
    Generates a sinusoidal regression model from a given data set

    Parameters
    ----------
    data : list of lists of int or float
        List of lists of numbers representing a collection of coordinate pairs; it must include at least 10 pairs
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    TypeError
        First argument must be a 2-dimensional list
    TypeError
        Elements nested within first argument must be integers or floats
    ValueError
        First argument must contain at least 10 elements
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    model['constants'] : list of float
        Coefficients of the resultant sinusoidal model; the first element is the vertical stretch factor, the second element is the horizontal stretch factor, the third element is the horizontal shift, and the fourth element is the vertical shift
    model['evaluations']['equation'] : func
        Function that evaluates the equation of the sinusoidal model at a given numeric input (e.g., model['evaluations']['equation'](10) would evaluate the equation of the sinusoidal model when the independent variable is 10)
    model['evaluations']['derivative'] : func
        Function that evaluates the first derivative of the sinusoidal model at a given numeric input (e.g., model['evaluations']['derivative'](10) would evaluate the first derivative of the sinusoidal model when the independent variable is 10)
    model['evaluations']['integral'] : func
        Function that evaluates the integral of the sinusoidal model at a given numeric input (e.g., model['evaluations']['integral'](10) would evaluate the integral of the sinusoidal model when the independent variable is 10)
    model['points']['roots'] : list of lists of float or str
        List of lists of numbers representing the coordinate pairs of all the x-intercepts of the sinusoidal model (will contain either `None` or an initial set of points within two periods along with general terms for finding the other points)
    model['points']['maxima'] : list of lists of float or str
        List of lists of numbers representing the coordinate pairs of all the maxima of the sinusoidal model (will contain an initial set of points within two periods along with a general term for finding the other points)
    model['points']['minima'] : list of lists of float or str
        List of lists of numbers representing the coordinate pairs of all the minima of the sinusoidal model (will contain an initial set of points within two periods along with a general term for finding the other points)
    model['points']['inflections'] : list of lists of float or str
        List of lists of numbers representing the coordinate pairs of all the inflection points of the sinusoidal model (will contain an initial set of points within two periods along with a general term for finding the other points)
    model['accumulations']['range'] : float
        Total area under the curve represented by the sinusoidal model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided (i.e., over the range)
    model['accumulations']['iqr'] : float
        Total area under the curve represented by the sinusoidal model between the first and third quartiles of all the independent coordinates originally provided (i.e., over the interquartile range)
    model['averages']['range']['average_value_derivative'] : float
        Average rate of change of the curve represented by the sinusoidal model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_derivative'] : list of float or str
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['range']['average_value_integral'] : float
        Average value of the curve represented by the sinusoidal model between the smallest independent coordinate originally provided and the largest independent coordinate originally provided
    model['averages']['range']['mean_values_integral'] : list of float or str
        All points between the smallest independent coordinate originally provided and the largest independent coordinate originally provided where their value equals the function's average value over that interval
    model['averages']['iqr']['average_value_derivative'] : float
        Average rate of change of the curve represented by the sinusoidal model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_derivative'] : list of float or str
        All points between the first and third quartiles of all the independent coordinates originally provided where their instantaneous rate of change equals the function's average rate of change over that interval
    model['averages']['iqr']['average_value_integral'] : float
        Average value of the curve represented by the sinusoidal model between the first and third quartiles of all the independent coordinates originally provided
    model['averages']['iqr']['mean_values_integral'] : list of float or str
        All points between the first and third quartiles of all the independent coordinates originally provided where their value equals the function's average value over that interval
    model['correlation'] : float
        Correlation coefficient indicating how well the model fits the original data set (values range between 0.0, implying no fit, and 1.0, implying a perfect fit)

    See Also
    --------
    :func:`~regressions.analyses.equations.sinusoidal.sinusoidal_equation`, :func:`~regressions.analyses.derivatives.sinusoidal.sinusoidal_derivatives`, :func:`~regressions.analyses.integrals.sinusoidal.sinusoidal_integral`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`, :func:`~regressions.statistics.correlation.correlation_coefficient`, :func:`~regressions.execute.run_all`

    Notes
    -----
    - Provided ordered pairs for the data set: :math:`p_i = \\{ (p_{1,x}, p_{1,y}), (p_{2,x}, p_{2,y}), \\cdots, (p_{n,x}, p_{n,y}) \\}`
    - Provided values for the independent variable: :math:`X_i = \\{ p_{1,x}, p_{2,x}, \\cdots, p_{n,x} \\}`
    - Provided values for the dependent variable: :math:`Y_i = \\{ p_{1,y}, p_{2,y}, \\cdots, p_{n,y} \\}`
    - Minimum value of the provided values for the independent variable: :math:`X_{min} \\leq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - Maximum value of the provided values for the independent variable: :math:`X_{max} \\geq p_{j,x}, \\forall p_{j,x} \\in X_i`
    - First quartile of the provided values for the independent variable: :math:`X_{Q1}`
    - Third quartile of the provided values for the independent variable: :math:`X_{Q3}`
    - Mean of all provided values for the dependent variable: :math:`\\bar{y} = \\frac{1}{n}\\cdot{\\sum\\limits_{i=1}^n Y_i}`
    - Resultant values for the coefficients of the sinusoidal model: :math:`C_i = \\{ a, b, c, d \\}`
    - Standard form for the equation of the sinusoidal model: :math:`f(x) = a\\cdot{\\sin(b\\cdot(x - c))} + d`
    - First derivative of the sinusoidal model: :math:`f'(x) = ab\\cdot{\\cos(b\\cdot(x - c))}`
    - Second derivative of the sinusoidal model: :math:`f''(x) = -ab^2\\cdot{\\sin(b\\cdot(x - c))}`
    - Integral of the sinusoidal model: :math:`F(x) = -\\frac{a}{b}\\cdot{\\cos(b\\cdot(x - c))} + d\\cdot{x}`
    - Potential x-values of the roots of the sinusoidal model: :math:`x_{intercepts} = \\{ c + \\frac{1}{b}\\cdot{\\left(\\sin^{-1}(-\\frac{d}{a}) + 2\\pi\\cdot{k} \\right)}, c + \\frac{1}{b}\\cdot{\\left(-\\sin^{-1}(-\\frac{d}{a}) + \\pi\\cdot(2k - 1) \\right)}, \\\\ c - \\frac{\\pi}{b}\\cdot(2k - 1) \\}`
        
        - :math:`k \\in \\mathbb{Z}`

    - Potential x-values of the maxima of the sinusoidal model: :math:`x_{maxima} = \\{ c + \\frac{\\pi}{b}\\cdot(\\frac{1}{2} + k) \\}`

        - :math:`k \\in \\mathbb{Z}`

    - Potential x-values of the minima of the sinusoidal model: :math:`x_{maxima} = \\{ c + \\frac{\\pi}{b}\\cdot(\\frac{1}{2} + k) \\}`

        - :math:`k \\in \\mathbb{Z}`

    - Potential x-values of the inflection points of the sinusoidal model: :math:`x_{inflections} = \\{ c + \\frac{\\pi}{b}\\cdot{k} \\}`

        - :math:`k \\in \\mathbb{Z}`

    - Accumulatation of the sinusoidal model over its range: :math:`A_{range} = \\int_{X_{min}}^{X_{max}} f(x) \\,dx`
    - Accumulatation of the sinusoidal model over its interquartile range: :math:`A_{iqr} = \\int_{X_{Q1}}^{X_{Q3}} f(x) \\,dx`
    - Average rate of change of the sinusoidal model over its range: :math:`m_{range} = \\frac{f(X_{max}) - f(X_{min})}{X_{max} - X_{min}}`
    - Potential x-values at which the sinusoidal model's instantaneous rate of change equals its average rate of change over its range: :math:`x_{m,range} = \\{ c + \\frac{1}{b}\\cdot{\\left(\\cos^{-1}(\\frac{m_{range}}{ab}) + \\pi\\cdot{k} \\right)}, c + \\frac{1}{b}\\cdot{\\left(-\\cos^{-1}(\\frac{m_{range}}{ab}) + 2\\pi\\cdot{k} \\right)} \\}`

        - :math:`k \\in \\mathbb{Z}`
    
    - Average value of the sinusoidal model over its range: :math:`v_{range} = \\frac{1}{X_{max} - X_{min}}\\cdot{A_{range}}`
    - Potential x-values at which the sinusoidal model's value equals its average value over its range: :math:`x_{v,range} = \\{ c + \\frac{1}{b}\\cdot{\\left(\\sin^{-1}(-\\frac{d - v_{range}}{a}) + 2\\pi\\cdot{k} \\right)}, c + \\frac{1}{b}\\cdot{\\left(-\\sin^{-1}(-\\frac{d - v_{range}}{a}) + \\pi\\cdot(2k - 1) \\right)}, \\\\ c + \\frac{\\pi}{b}\\cdot(2k - 1) \\}`

        - :math:`k \\in \\mathbb{Z}`

    - Average rate of change of the sinusoidal model over its interquartile range: :math:`m_{iqr} = \\frac{f(X_{Q3}) - f(X_{Q1})}{X_{Q3} - X_{Q1}}`
    - Potential x-values at which the sinusoidal model's instantaneous rate of change equals its average rate of change over its interquartile range: :math:`x_{m,iqr} = \\{ c + \\frac{1}{b}\\cdot{\\left(\\cos^{-1}(\\frac{m_{iqr}}{ab}) + \\pi\\cdot{k} \\right)}, c + \\frac{1}{b}\\cdot{\\left(-\\cos^{-1}(\\frac{m_{iqr}}{ab}) + 2\\pi\\cdot{k} \\right)} \\}`

        - :math:`k \\in \\mathbb{Z}`

    - Average value of the sinusoidal model over its interquartile range: :math:`v_{iqr} = \\frac{1}{X_{Q3} - X_{Q1}}\\cdot{A_{iqr}}`
    - Potential x-values at which the sinusoidal model's value equals its average value over its interquartile range: :math:`x_{v,iqr} = \\{ c + \\frac{1}{b}\\cdot{\\left(\\sin^{-1}(-\\frac{d - v_{iqr}}{a}) + 2\\pi\\cdot{k} \\right)}, c + \\frac{1}{b}\\cdot{\\left(-\\sin^{-1}(-\\frac{d - v_{iqr}}{a}) + \\pi\\cdot(2k - 1) \\right)}, \\\\ c + \\frac{\\pi}{b}\\cdot(2k - 1) \\}`

        - :math:`k \\in \\mathbb{Z}`

    - Predicted values based on the sinusoidal model: :math:`\\hat{y}_i = \\{ \\hat{y}_1, \\hat{y}_2, \\cdots, \\hat{y}_n \\}`
    - Residuals of the dependent variable: :math:`e_i = \\{ p_{1,y} - \\hat{y}_1, p_{2,y} - \\hat{y}_2, \\cdots, p_{n,y} - \\hat{y}_n \\}`
    - Deviations of the dependent variable: :math:`d_i = \\{ p_{1,y} - \\bar{y}, p_{2,y} - \\bar{y}, \\cdots, p_{n,y} - \\bar{y} \\}`
    - Sum of squares of residuals: :math:`SS_{res} = \\sum\\limits_{i=1}^n e_i^2`
    - Sum of squares of deviations: :math:`SS_{dev} = \\sum\\limits_{i=1}^n d_i^2`
    - Correlation coefficient for the sinusoidal model: :math:`r = \\sqrt{1 - \\frac{SS_{res}}{SS_{dev}}}`
    - |regression_analysis|

    Examples
    --------
    Import `sinusoidal_model` function from `regressions` library
        >>> from regressions.models.sinusoidal import sinusoidal_model
    Generate a sinusoidal regression model for the data set [[1, 3], [2, 8], [3, 3], [4, -2], [5, 3], [6, 8], [7, 3], [8, -2], [9, 3], [10, 8]], then print its coefficients, roots, total accumulation over its interquartile range, and correlation
        >>> model_perfect = sinusoidal_model([[1, 3], [2, 8], [3, 3], [4, -2], [5, 3], [6, 8], [7, 3], [8, -2], [9, 3], [10, 8]])
        >>> print(model_perfect['constants'])
        [-5.0, 1.5708, 3.0, 3.0]
        >>> print(model_perfect['points']['roots'])
        [[3.4097, 0.0], [4.5903, 0.0], [7.4097, 0.0], [8.5903, 0.0], ['3.4097 + 4.0k', 0.0], ['4.5903 + 4.0k', 0.0]]
        >>> print(model_perfect['accumulations']['iqr'])
        11.8168
        >>> print(model_perfect['correlation'])
        1.0
    Generate a sinusoidal regression model for the data set [[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]], then print its coefficients, inflections, total accumulation over its range, and correlation
        >>> model_agnostic = sinusoidal_model([[1, 32], [2, 25], [3, 14], [4, 23], [5, 39], [6, 45], [7, 42], [8, 49], [9, 36], [10, 33]])
        >>> print(model_agnostic['constants'])
        [14.0875, 0.7119, -3.7531, 34.2915]
        >>> print(model_agnostic['points']['inflections'])
        [[5.0729, 34.2915], [9.4859, 34.2915], [13.8985, 34.2915], [18.3114, 34.2915], ['5.0729 + 4.413k', 34.2915]]
        >>> print(model_agnostic['accumulations']['range'])
        307.8897
        >>> print(model_agnostic['correlation'])
        0.9264
    """
    # Handle input errors
    matrix_of_scalars(data, 'first')
    long_vector(data)
    positive_integer(precision)

    # Store independent and dependent variable values separately
    independent_variable = single_dimension(data, 1)
    dependent_variable = single_dimension(data, 2)

    # Determine key values for bounds
    independent_max = max(independent_variable)
    independent_min = min(independent_variable)
    independent_range = independent_max - independent_min
    dependent_max = max(dependent_variable)
    dependent_min = min(dependent_variable)
    dependent_range = dependent_max - dependent_min

    # Circumvent errors with bounds
    if independent_range == 0:
        independent_range = 1
    if dependent_range == 0:
        dependent_range = 1
        dependent_max += 1

    # Create function to guide model generation
    def sinusoidal_fit(variable, first_constant, second_constant,
                       third_constant, fourth_constant):
        evaluation = first_constant * sin(
            second_constant * (variable - third_constant)) + fourth_constant
        return evaluation

    # Create list to store coefficients of generated equation
    solution = []

    # Handle normal case
    try:
        # Generate model
        parameters, covariance = curve_fit(
            sinusoidal_fit,
            independent_variable,
            dependent_variable,
            bounds=[(-dependent_range, -inf, -independent_range,
                     dependent_min),
                    (dependent_range, inf, independent_range, dependent_max)])
        solution = list(parameters)

    # Narrow bounds in event of runtime error
    except RuntimeError:
        # Regenerate model within tighter parameters
        parameters, covariance = curve_fit(
            sinusoidal_fit,
            independent_variable,
            dependent_variable,
            bounds=[(dependent_range - 1, -independent_range,
                     -independent_range, dependent_min),
                    (dependent_range + 1, independent_range, independent_range,
                     dependent_max)])
        solution = list(parameters)

    # Eliminate zeroes from solution
    coefficients = no_zeroes(solution, precision)

    # Generate evaluations for function, derivative, and integral
    equation = sinusoidal_equation(*coefficients, precision)
    derivative = sinusoidal_derivatives(*coefficients,
                                        precision)['first']['evaluation']
    integral = sinusoidal_integral(*coefficients, precision)['evaluation']

    # Determine key points of graph
    points = key_coordinates('sinusoidal', coefficients, precision)
    final_roots = shifted_coordinates_within_range(points['roots'],
                                                   independent_min,
                                                   independent_max, precision)
    final_maxima = shifted_coordinates_within_range(points['maxima'],
                                                    independent_min,
                                                    independent_max, precision)
    final_minima = shifted_coordinates_within_range(points['minima'],
                                                    independent_min,
                                                    independent_max, precision)
    final_inflections = shifted_coordinates_within_range(
        points['inflections'], independent_min, independent_max, precision)

    # Generate values for lower and upper bounds
    five_numbers = five_number_summary(independent_variable, precision)
    min_value = five_numbers['minimum']
    max_value = five_numbers['maximum']
    q1 = five_numbers['q1']
    q3 = five_numbers['q3']

    # Calculate accumulations
    accumulated_range = accumulated_area('sinusoidal', coefficients, min_value,
                                         max_value, precision)
    accumulated_iqr = accumulated_area('sinusoidal', coefficients, q1, q3,
                                       precision)

    # Determine average values and their points
    averages_range = average_values('sinusoidal', coefficients, min_value,
                                    max_value, precision)
    averages_iqr = average_values('sinusoidal', coefficients, q1, q3,
                                  precision)

    # Create list of predicted outputs
    predicted = []
    for element in independent_variable:
        predicted.append(equation(element))

    # Calculate correlation coefficient for model
    accuracy = correlation_coefficient(dependent_variable, predicted,
                                       precision)

    # Package preceding results in multiple dictionaries
    evaluations = {
        'equation': equation,
        'derivative': derivative,
        'integral': integral
    }
    points = {
        'roots': final_roots,
        'maxima': final_maxima,
        'minima': final_minima,
        'inflections': final_inflections
    }
    accumulations = {'range': accumulated_range, 'iqr': accumulated_iqr}
    averages = {'range': averages_range, 'iqr': averages_iqr}

    # Package all dictionaries in single dictionary to return
    result = {
        'constants': coefficients,
        'evaluations': evaluations,
        'points': points,
        'accumulations': accumulations,
        'averages': averages,
        'correlation': accuracy
    }
    return result