예제 #1
0
 def test_select_integers_excluded_raises(self):
     with self.assertRaises(Exception) as context:
         select_integers(1, choices)
     self.assertEqual(type(context.exception), ValueError)
     self.assertEqual(
         str(context.exception),
         'Argument must be one of the following integers: [4, 5, 6]')
예제 #2
0
def quartile_value(data, q):
    """
    Determines the first, second, or third quartile values of a data set

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze
    q : int
        Number determining which quartile to provide

    Raises
    ------
    TypeError
        First argument must be a 1-dimensional list
    TypeError
        Elements of first argument must be integers or floats
    ValueError
        Second argument must be an integer contained within the set [1, 2, 3]

    Returns
    -------
    quartile : int or float
        Quartile value of the data set

    See Also
    --------
    :func:`~regressions.statistics.sort.sorted_list`, :func:`~regressions.statistics.halve.half`, :func:`~regressions.statistics.minimum.minimum_value`, :func:`~regressions.statistics.maximum.maximum_value`, :func:`~regressions.statistics.median.median_value`

    Notes
    -----
    - Ordered set of numbers: :math:`a_i = ( a_1, a_2, \\cdots, a_n )`
    - For sets with an odd amount of numbers:
        
        - First quartile: :math:`Q_1 = a_{\\lceil n/4 \\rceil}`
        - Second quartile: :math:`Q_2 = a_{\\lceil n/2 \\rceil}`
        - Third quartile: :math:`Q_3 = a_{\\lceil 3n/4 \\rceil}`
    
    - For sets with an even amount of numbers:

        - If :math:`n \\text{ mod } 4 \\neq 0`:

            - First quartile: :math:`Q_1 = a_{\\lceil n/4 \\rceil}`
            - Second quartile: :math:`Q_2 = \\frac{a_{n/2} + a_{n/2 + 1}}{2}`
            - Third quartile: :math:`Q_3 = a_{\\lceil 3n/4 \\rceil}`
        
        - If :math:`n \\text{ mod } 4 = 0`:

            - First quartile: :math:`Q_1 = \\frac{a_{n/4} + a_{n/4 + 1}}{2}`
            - Second quartile: :math:`Q_2 = \\frac{a_{n/2} + a_{n/2 + 1}}{2}`
            - Third quartile: :math:`Q_3 = \\frac{a_{3n/4} + a_{3n/4 + 1}}{2}`

    - |quartiles|

    Examples
    --------
    Import `quartile_value` function from `regressions` library
        >>> from regressions.statistics.quartiles import quartile_value
    Determine the first quartile of the set [21, 53, 3, 68, 43, 9, 72, 19, 20, 1]
        >>> quartile_1 = quartile_value([21, 53, 3, 68, 43, 9, 72, 19, 20, 1], 1)
        >>> print(quartile_1)
        9
    Determine the third quartile of the set [12, 81, 13, 8, 42, 72, 91, 20, 20]
        >>> quartile_3 = quartile_value([12, 81, 13, 8, 42, 72, 91, 20, 20], 3)
        >>> print(quartile_3)
        76.5
    """
    # Handle input errors
    vector_of_scalars(data, 'first')
    select_integers(q, [1, 2, 3])

    # Split input in half
    halved_data = half(data)

    # Create number to return
    result = 0

    # Determine Q2 by taking the median of all elements
    if q == 2:
        result = median_value(data)

    # Determine Q1 by taking the median of the lower half of elements
    elif q == 1:
        result = median_value(halved_data['lower'])

    # Determine Q3 by taking the median of the upper half of elements
    elif q == 3:
        result = median_value(halved_data['upper'])

    # Return result
    return result
예제 #3
0
def critical_points(equation_type,
                    coefficients,
                    derivative_level,
                    precision=4):
    """
    Calculates the critical points of a specific function at a certain derivative level

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which critical points must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    derivative_level : int
        Integer corresponding to which derivative to investigate for critical points (1 for the first derivative and 2 for the second derivative)
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    ValueError
        First argument must be either 'linear', 'quadratic', 'cubic', 'hyperbolic', 'exponential', 'logarithmic', 'logistic', or 'sinusoidal'
    TypeError
        Second argument must be a 1-dimensional list containing elements that are integers or floats
    ValueError
        Third argument must be one of the following integers: [1, 2]
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    points : list of float or str
        Values of the x-coordinates at which the original function's derivative either crosses the x-axis or does not exist; if the function is sinusoidal, then only five results within a two-period interval will be listed, but a general form will also be included; if the derivative has no critical points, then it will return a list of `None`

    See Also
    --------
    - Roots for key functions: :func:`~regressions.analyses.roots.linear.linear_roots`, :func:`~regressions.analyses.roots.quadratic.quadratic_roots`, :func:`~regressions.analyses.roots.cubic.cubic_roots`, :func:`~regressions.analyses.roots.hyperbolic.hyperbolic_roots`, :func:`~regressions.analyses.roots.exponential.exponential_roots`, :func:`~regressions.analyses.roots.logarithmic.logarithmic_roots`, :func:`~regressions.analyses.roots.logistic.logistic_roots`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`
    - Graphical analysis: :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.points.key_coordinates`

    Notes
    -----
    - Domain of a function: :math:`x_i = \\{ x_1, x_2, \\cdots, x_n \\}`
    - Potential critical points of the derivative of the function: :math:`x_c = \\{ c \\mid c \\in x_i, f'(c) = 0 \\cup f'(c) = \\varnothing \\}`
    - |critical_points|

    Examples
    --------
    Import `critical_points` function from `regressions` library
        >>> from regressions.analyses.criticals import critical_points
    Calulate the critical points of the second derivative of a cubic function with coefficients 2, 3, 5, and 7
        >>> points_cubic = critical_points('cubic', [2, 3, 5, 7], 2)
        >>> print(points_cubic)
        [-0.5]
    Calulate the critical points of the first derivative of a sinusoidal function with coefficients 2, 3, 5, and 7
        >>> points_sinusoidal = critical_points('sinusoidal', [2, 3, 5, 7], 1)
        >>> print(points_sinusoidal)
        [5.5236, 6.5708, 7.618, 8.6652, 9.7124, '5.5236 + 1.0472k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    select_integers(derivative_level, [1, 2], 'third')
    positive_integer(precision)

    # Create list to return
    results = []

    # Determine critical points for first derivative based on equation type
    if derivative_level == 1:
        if equation_type == 'linear':
            results = linear_roots_first_derivative(*coefficients, precision)
        elif equation_type == 'quadratic':
            results = quadratic_roots_first_derivative(*coefficients,
                                                       precision)
        elif equation_type == 'cubic':
            results = cubic_roots_first_derivative(*coefficients, precision)
        elif equation_type == 'hyperbolic':
            results = hyperbolic_roots_first_derivative(
                *coefficients, precision)
        elif equation_type == 'exponential':
            results = exponential_roots_first_derivative(
                *coefficients, precision)
        elif equation_type == 'logarithmic':
            results = logarithmic_roots_first_derivative(
                *coefficients, precision)
        elif equation_type == 'logistic':
            results = logistic_roots_first_derivative(*coefficients, precision)
        elif equation_type == 'sinusoidal':
            results = sinusoidal_roots_first_derivative(
                *coefficients, precision)

    # Determine critical points for second derivative based on equation type
    elif derivative_level == 2:
        if equation_type == 'linear':
            results = linear_roots_second_derivative(*coefficients, precision)
        elif equation_type == 'quadratic':
            results = quadratic_roots_second_derivative(
                *coefficients, precision)
        elif equation_type == 'cubic':
            results = cubic_roots_second_derivative(*coefficients, precision)
        elif equation_type == 'hyperbolic':
            results = hyperbolic_roots_second_derivative(
                *coefficients, precision)
        elif equation_type == 'exponential':
            results = exponential_roots_second_derivative(
                *coefficients, precision)
        elif equation_type == 'logarithmic':
            results = logarithmic_roots_second_derivative(
                *coefficients, precision)
        elif equation_type == 'logistic':
            results = logistic_roots_second_derivative(*coefficients,
                                                       precision)
        elif equation_type == 'sinusoidal':
            results = sinusoidal_roots_second_derivative(
                *coefficients, precision)
    return results
예제 #4
0
 def test_select_integers_included(self):
     select_integers_included = select_integers(5, choices)
     self.assertEqual(
         select_integers_included,
         'Argument is one of the following integers: [4, 5, 6]')
예제 #5
0
def sign_chart(equation_type, coefficients, derivative_level, precision=4):
    """
    Creates a sign chart for a given derivative

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which the sign chart must be constructed (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    derivative_level : int
        Integer corresponding to which derivative to investigate for sign chart (1 for the first derivative and 2 for the second derivative)
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the results

    Raises
    ------
    ValueError
        First argument must be either 'linear', 'quadratic', 'cubic', 'hyperbolic', 'exponential', 'logarithmic', 'logistic', or 'sinusoidal'
    TypeError
        Second argument must be a 1-dimensional list containing elements that are integers or floats
    ValueError
        Third argument must be one of the following integers: [1, 2]
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    chart : list of str and float
        Strings describing the sign (e.g., 'positive', 'negative') of the derivative between its critical points; as a result, its elements will alternate between strings (indicating the signs) and floats (indicating the end points); if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form to determine other end points will also be included

    See Also
    --------
    - Roots for key functions: :func:`~regressions.analyses.roots.linear.linear_roots`, :func:`~regressions.analyses.roots.quadratic.quadratic_roots`, :func:`~regressions.analyses.roots.cubic.cubic_roots`, :func:`~regressions.analyses.roots.hyperbolic.hyperbolic_roots`, :func:`~regressions.analyses.roots.exponential.exponential_roots`, :func:`~regressions.analyses.roots.logarithmic.logarithmic_roots`, :func:`~regressions.analyses.roots.logistic.logistic_roots`, :func:`~regressions.analyses.roots.sinusoidal.sinusoidal_roots`
    - Graphical analysis: :func:`~regressions.analyses.criticals.critical_points`, :func:`~regressions.analyses.points.key_coordinates`

    Notes
    -----
    - Critical points for the derivative of a function: :math:`c_i = \\{ c_1, c_2, c_3,  \\cdots, c_{n-1}, c_n \\}`
    - Midpoints and key values of the intervals demarcated by the critical points: :math:`m_i = \\{ c_1 - 1,  \\frac{c_1+c_2}{2}, \\frac{c_2+c_3}{2}, \\cdots, \\frac{c_{n-1}+c_n}{2}, c_n + 1 \\}`
    - Values of the derivative within the intervals: :math:`v_i = \\{ v_1, v_2, v_3, v_4 \\cdots, v_{n-1}, v_n, v_{n+1} \\}`
    - Sign chart: :math:`s = ( v_1, c_1, v_2, c_2, v_3, c_3, v_4, \\dots, v_{n-1}, c_{n-1}, v_n, c_n, v_{n+1} )`

        - :math:`v_j = negative` if :math:`f'(m_j) < 0`
        - :math:`v_j = constant` if :math:`f'(m_j) = 0`
        - :math:`v_j = positve` if :math:`f'(m_j) > 0`

    - |intervals|

    Examples
    --------
    Import `sign_chart` function from `regressions` library
        >>> from regressions.analyses.intervals import sign_chart
    Create the sign chart for the first derivative of a cubic function with coefficients 1, -15, 63, and -7
        >>> chart_cubic = sign_chart('cubic', [1, -15, 63, -7], 1)
        >>> print(chart_cubic)
        ['positive', 3.0, 'negative', 7.0, 'positive']
    Create the sign chart for the second derivative of a sinusoidal function with coefficients 2, 3, 5, and 7
        >>> chart_sinusoidal = sign_chart('sinusoidal', [2, 3, 5, 7], 2)
        >>> print(chart_sinusoidal)
        ['positive', 5.0, 'negative', 6.0472, 'positive', 7.0944, 'negative', 8.1416, 'positive', 9.1888, 'negative', '5.0 + 1.0472k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    select_integers(derivative_level, [1, 2], 'third')
    positive_integer(precision)

    # Create first and second derivatives based on equation type
    both_derivatives = {}
    if equation_type == 'linear':
        both_derivatives = linear_derivatives(*coefficients, precision)
    elif equation_type == 'quadratic':
        both_derivatives = quadratic_derivatives(*coefficients, precision)
    elif equation_type == 'cubic':
        both_derivatives = cubic_derivatives(*coefficients, precision)
    elif equation_type == 'hyperbolic':
        both_derivatives = hyperbolic_derivatives(*coefficients, precision)
    elif equation_type == 'exponential':
        both_derivatives = exponential_derivatives(*coefficients, precision)
    elif equation_type == 'logarithmic':
        both_derivatives = logarithmic_derivatives(*coefficients, precision)
    elif equation_type == 'logistic':
        both_derivatives = logistic_derivatives(*coefficients, precision)
    elif equation_type == 'sinusoidal':
        both_derivatives = sinusoidal_derivatives(*coefficients, precision)

    # Grab specific derivative evaluation based on derivative level
    derivative = lambda x: x
    if derivative_level == 1:
        derivative = both_derivatives['first']['evaluation']
    elif derivative_level == 2:
        derivative = both_derivatives['second']['evaluation']

    # Create critical points for specific derivative
    points = critical_points(equation_type, coefficients, derivative_level,
                             precision)

    # Create sign chart for specific derivative
    result = []

    # Handle no critical points
    if points[0] == None:
        # Test an arbitrary number
        if derivative(10) > 0:
            result = ['positive']
        elif derivative(10) < 0:
            result = ['negative']
        else:
            result = ['constant']

    # Handle exactly one critical point
    elif len(points) == 1:
        # Generate numbers to test
        turning_point = points[0]
        before = turning_point - 1
        after = turning_point + 1

        # Test numbers
        if derivative(before) > 0:
            before = 'positive'
        elif derivative(before) < 0:
            before = 'negative'
        if derivative(after) > 0:
            after = 'positive'
        elif derivative(after) < 0:
            after = 'negative'

        # Store sign chart
        result = [before, turning_point, after]

    # Handle exactly two critical points
    elif len(points) == 2:
        # Generate numbers to test
        sorted_points = sorted_list(points)
        first_point = sorted_points[0]
        second_point = sorted_points[1]
        middle = (first_point + second_point) / 2
        before = first_point - 1
        after = second_point + 1

        # Test numbers
        if derivative(before) > 0:
            before = 'positive'
        elif derivative(before) < 0:
            before = 'negative'
        if derivative(middle) > 0:
            middle = 'positive'
        elif derivative(middle) < 0:
            middle = 'negative'
        if derivative(after) > 0:
            after = 'positive'
        elif derivative(after) < 0:
            after = 'negative'

        # Store sign chart
        result = [before, first_point, middle, second_point, after]

    # Handle more than two critical points
    else:
        # Separate numerical inputs from string inputs
        separated_points = separate_elements(points)
        numerical_points = separated_points['numerical']
        other_points = separated_points['other']

        # Generate numbers to test
        sorted_points = sorted_list(numerical_points)
        difference = sorted_points[1] - sorted_points[0]
        halved_difference = difference / 2
        before_first = sorted_points[0] - halved_difference
        between_first_second = sorted_points[0] + halved_difference
        between_second_third = sorted_points[1] + halved_difference
        between_third_fourth = sorted_points[2] + halved_difference
        between_fourth_last = sorted_points[3] + halved_difference
        after_last = sorted_points[4] + halved_difference
        test_points = [
            before_first, between_first_second, between_second_third,
            between_third_fourth, between_fourth_last, after_last
        ]

        # Test numbers
        signs = []
        for point in test_points:
            if derivative(point) > 0:
                signs.append('positive')
            elif derivative(point) < 0:
                signs.append('negative')

        # Store sign chart
        result = [
            signs[0], sorted_points[0], signs[1], sorted_points[1], signs[2],
            sorted_points[2], signs[3], sorted_points[3], signs[4],
            sorted_points[4], signs[5], *other_points
        ]
    return result