Esempio n. 1
0
 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')
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
 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')
Esempio n. 7
0
 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')