def test_vector_strings_nested_raises(self): with self.assertRaises(Exception) as context: allow_none_vector(bad_vector_nested) self.assertEqual(type(context.exception), TypeError) self.assertEqual( str(context.exception), 'Elements of argument must be integers, floats, strings, or None')
def rounded_list(numbers, precision=4): # Handle input errors allow_none_vector(numbers, 'first') positive_integer(precision) # Create list to return results = [] # Iterate over input for number in numbers: # Store rounded values of input in list to return results.append(rounded_value(number, precision)) # Return results return results
def points_within_range(points, start, end): """ Eliminates all values from a set of points that fall below a lower bound or above an upper bound Parameters ---------- points : list of int or float or str Set of points to narrow down to only those within a certain range start : int or float Lower bound of range into which the initial value must be adjusted (final value should be greater than or equal to start) end : int or float Upper bound of range into which the initial value must be adjusted (final value should be less than or equal to end) Raises ------ TypeError First argument must be a 1-dimensional list containing elements that are integers, floats, strings, or None TypeError Second and third arguments must be integers or floats ValueError Second argument must be less than or equal to third argument Returns ------- selected_points : list of int or float or str List of all values from original list that fall within specified range; may return a list of None if no points from the original list fall within range or if original list only contained None See Also -------- :func:`~regressions.vectors.separate.separate_elements`, :func:`~regressions.statistics.ranges.shift_into_range`, :func:`~regressions.analyses.mean_values.mean_values_derivative`, :func:`~regressions.analyses.mean_values.mean_values_integral` Notes ----- - Initial set of points: :math:`p_i = \\{ p_1, p_2, \\cdots, p_n \\}` - Lower bound of range: :math:`b_l` - Upper bound of range: :math:`b_u` - Adjusted set of points within range: :math:`r_i = \\{ r \\mid r \\in p_i, r \\geq b_l, r \\leq b_u \\}` Examples -------- Import `points_within_range` function from `regressions` library >>> from regressions.analyses.points import points_within_range Eliminate all points above 19 or below 6 in the set [1, 5, 6, 7, 18, 20, 50, 127] >>> selected_points_int = points_within_range([1, 5, 6, 7, 18, 20, 50, 127], 6, 19) >>> print(selected_points_int) [6, 7, 18] Eliminate all points above 243.7821 or below 198.1735 in the set [542.1234, 237.9109, -129.3214, 199.4321, 129.3214] >>> selected_points_float = points_within_range([542.1234, 237.9109, -129.3214, 199.4321, 129.3214], 198.1735, 243.7821) >>> print(selected_points_float) [237.9109, 199.4321] """ # Handle input errors allow_none_vector(points, 'first') compare_scalars(start, end, 'second', 'third') # Separate numerical results from string results separated_results = separate_elements(points) numerical_results = separated_results['numerical'] other_results = separated_results['other'] # Eliminate numerical results outside of range selected_results = [x for x in numerical_results if x >= start and x <= end] # Create list to return final_results = [] # Handle no results if not selected_results and not other_results: final_results.append(None) # Handle general case else: final_results.extend(selected_results + other_results) # Return results return final_results
def coordinate_pairs(equation_type, coefficients, inputs, point_type = 'point', precision = 4): """ Creates a list of coordinate pairs from a set of inputs Parameters ---------- equation_type : str Name of the type of function for which coordinate pairs must be determined (e.g., 'linear', 'quadratic') coefficients : list of int or float Coefficients to use to generate the equation to investigate inputs : list of int or float or str X-coordinates to use to generate the y-coordinates for each coordinate pair point_type : str, default='point' Name of the type of point that describes all points which must be generated (e.g., 'intercepts', 'maxima') 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 TypeError Third argument must be a 1-dimensional list containing elements that are integers, floats, strings, or None ValueError Fourth argument must be either 'point', 'intercepts', 'maxima', 'minima', or 'inflections' ValueError Last argument must be a positive integer Returns ------- points : list of float or str List containing lists of coordinate pairs, in which the second element of the inner lists are floats and the first elements of the inner lists are either floats or strings (the latter for general forms); may return a list of None if inputs list contained None See Also -------- :func:`~regressions.vectors.generate.generate_elements`, :func:`~regressions.vectors.unify.unite_vectors` Notes ----- - Set of x-coordinates of points: :math:`x_i = \\{ x_1, x_2, \\cdots, x_n \\}` - Set of y-coordinates of points: :math:`y_i = \\{ y_1, y_2, \\cdots, y_n \\}` - Set of coordinate pairs of points: :math:`p_i = \\{ (x_1, y_1), (x_2, y_2), \\cdots, (x_n, y_n) \\}` Examples -------- Import `coordinate_pairs` function from `regressions` library >>> from regressions.analyses.points import coordinate_pairs Generate a list of coordinate pairs for a cubic function with coefficients 2, 3, 5, and 7 based off x-coordinates of 1, 2, 3, and 4 >>> points_cubic = coordinate_pairs('cubic', [2, 3, 5, 7], [1, 2, 3, 4]) >>> print(points_cubic) [[1.0, 17.0], [2.0, 45.0], [3.0, 103.0], [4.0, 203.0]] Generate a list of coordinate pairs for a sinusoidal function with coefficients 2, 3, 5, and 7 based off x-coordinates of 1, 2, 3, and 4 >>> points_sinusoidal = coordinate_pairs('sinusoidal', [2, 3, 5, 7], [1, 2, 3, 4]) >>> print(points_sinusoidal) [[1.0, 8.0731], [2.0, 6.1758], [3.0, 7.5588], [4.0, 6.7178]] Generate a list of coordinate pairs for a quadratic function with coefficients 1, -5, and 6 based off x-coordinates of 2 and 3 (given that the resultant coordinates will be x-intercepts) >>> points_quadratic = coordinate_pairs('quadratic', [1, -5, 6], [2, 3], 'intercepts') >>> print(points_quadratic) [[2.0, 0.0], [3.0, 0.0]] """ # Handle input errors select_equations(equation_type) vector_of_scalars(coefficients, 'second') allow_none_vector(inputs, 'third') select_points(point_type, 'fourth') positive_integer(precision) # Create equations for evaluating inputs (based on equation type) equation = lambda x : x if equation_type == 'linear': equation = linear_equation(*coefficients, precision) elif equation_type == 'quadratic': equation = quadratic_equation(*coefficients, precision) elif equation_type == 'cubic': equation = cubic_equation(*coefficients, precision) elif equation_type == 'hyperbolic': equation = hyperbolic_equation(*coefficients, precision) elif equation_type == 'exponential': equation = exponential_equation(*coefficients, precision) elif equation_type == 'logarithmic': equation = logarithmic_equation(*coefficients, precision) elif equation_type == 'logistic': equation = logistic_equation(*coefficients, precision) elif equation_type == 'sinusoidal': equation = sinusoidal_equation(*coefficients, precision) # Round inputs rounded_inputs = [] for point in inputs: if isinstance(point, (int, float)): rounded_inputs.append(rounded_value(point, precision)) else: rounded_inputs.append(point) # Create empty lists outputs = [] coordinates = [] # Handle no points if rounded_inputs[0] == None: coordinates.append(None) # Fill outputs list with output value at each input else: for value in rounded_inputs: # Circumvent inaccurate rounding if point_type == 'intercepts': outputs.append(0.0) # Evaluate function at inputs else: # Evaluate numerical inputs if isinstance(value, (int, float)): output = equation(value) rounded_output = rounded_value(output, precision) outputs.append(rounded_output) # Handle non-numerical inputs else: outputs.append(outputs[0]) # Unite inputs and outputs for maxima into single list coordinates.extend(unite_vectors(rounded_inputs, outputs)) # Return final coordinate pairs return coordinates
def separate_elements(vector): """ Separates a single vector into two vectors based their data types (numerical and non-numerical) Parameters ---------- vector : list of int or float or str List containing elements of various types: integers, floats, strings, or None Raises ------ TypeError Elements of argument must be integers, floats, strings, or None Returns ------- separate_vectors['numerical'] : list of int or float List containing only the integer or float elements from the input vector; may be an empty list if input vector contained no integer or float elements separate_vectors['other'] : list of str List containing only the string or None elements from the input vector; may be an empty list if input vector contained no string elements and did not merely contain None See Also -------- :func:`~regressions.vectors.generate_generate_elements`, :func:`~regressions.vectors.unify.unite_vectors` Notes ----- - Set of all real numbers: :math:`\\mathbb{R}` - Set of all strings: :math:`\\mathbb{S}` - Set containing None: :math:`\\{ \\emptyset \\}` - Set of all real numbers, all strings, and None: :math:`\\mathbb{A} = \\{ \\mathbb{R}, \\mathbb{S}, \\emptyset \\}` - Set of mixed elements: :math:`M = \\{ m \\mid m \\in \\mathbb{A} \\}` - Set of numerical elements from mixed elements: :math:`N = \\{ n \\mid n \\in M, n \\in \\mathbb{R} \\}` - Set of non-numerical elements from mixed elements: :math:`O = \\{ o \\mid o \\in M, o \\in \\mathbb{S} \\cup \\emptyset \\}` Examples -------- Import `separate_elements` function from `regressions` library >>> from regressions.vectors.separate import separate_elements Separate [1, 'two', 3, 'four'] into two vectors based on its data types >>> separate_vectors_mixed = separate_elements([1, 'two', 3, 'four']) >>> print(separate_vectors_mixed['numerical']) [1, 3] >>> print(separate_vectors_mixed['other']) ['two', 'four'] Separate [None] into two vectors based on its data types >>> separate_vectors_none = separate_elements([None]) >>> print(separate_vectors_none['numerical']) [] >>> print(separate_vectors_none['other']) [None] """ # Handle input errors allow_none_vector(vector) # Create lists to store separate values numerical_elements = [] other_elements = [] # Iterate over input for element in vector: # Store numerical elements if isinstance(element, (int, float)): numerical_elements.append(element) # Store non-numerical elements else: other_elements.append(element) # Package both types of element in single dictionary to return results = {'numerical': numerical_elements, 'other': other_elements} return results
def test_allow_none_vector_none(self): allow_none_vector_none = allow_none_vector(none_vector) self.assertEqual( allow_none_vector_none, 'Elements of argument are integers, floats, strings, or None')
def test_allow_none_vector_scalars(self): allow_none_vector_scalars = allow_none_vector(first_vector) self.assertEqual( allow_none_vector_scalars, 'Elements of argument are integers, floats, strings, or None')