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]')
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
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
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]')
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