예제 #1
0
def mean_value(data):
    """
    Determines the arithmetic mean of a data set

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    mean : float
        Arithmetic mean of the data set

    See Also
    --------
    :func:`~regressions.statistics.summation.sum_value`, :func:`~regressions.statistics.median.median_value`, :func:`~regressions.statistics.correlation.correlation_coefficient`

    Notes
    -----
    - Set of numbers: :math:`a_i = \\{ a_1, a_2, \\cdots, a_n \\}`
    - Mean of all numbers in set: :math:`\\bar{a} = \\frac{1}{n}\\cdot{\\sum\\limits_{i=1}^n a_i}`
    - |mean|

    Examples
    --------
    Import `mean_value` function from `regressions` library
        >>> from regressions.statistics.mean import mean_value
    Determine the mean of the set [21, 53, 3, 68, 43, 9, 72, 19, 20, 1]
        >>> mean_even = mean_value([21, 53, 3, 68, 43, 9, 72, 19, 20, 1])
        >>> print(mean_even)
        30.9
    Determine the mean of the set [12, 81, 13, 8, 42, 72, 91, 20, 20]
        >>> mean_odd = mean_value([12, 81, 13, 8, 42, 72, 91, 20, 20])
        >>> print(mean_odd)
        39.888888888888886
    """
    # Handle input errors
    vector_of_scalars(data)

    # Calculate sum of all elements in input
    sum_of_data = sum_value(data)

    # Determine length of input
    length_of_data = len(data)

    # Calculate average
    average = sum_of_data / length_of_data

    # Convert average to float
    result = float(average)
    return result
예제 #2
0
def sum_value(data):
    """
    Calculates the sum of all elements in a data set

    Parameters
    ----------
    data : list of int or float
        List of numbers

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    total : float
        Number representing the sum of all elements in the original set

    See Also
    --------
    :func:`~regressions.statistics.mean.mean_value`, :func:`~regressions.statistics.correlation.correlation_coefficient`

    Notes
    -----
    - Set of numbers: :math:`a_i = \\{ a_1, a_2, \\cdots, a_n \\}`
    - Sum of all numbers in set: :math:`\\sum\\limits_{i=1}^n a_i = a_1 + a_2 + \\cdots + a_n`
    - |summation_notation|

    Examples
    --------
    Import `sum_value` function from `regressions` library
        >>> from regressions.statistics.summation import sum_value
    Find the total sum of all values in the array [2, 3, 5, 7]
        >>> total_1 = sum_value([2, 3, 5, 7])
        >>> print(total_1)
        17.0
    Find the total sum of all values in the array [1, -1, 1, -1]
        >>> total_2 = sum_value([1, -1, 1, -1])
        >>> print(total_2)
        0.0
    """
    # Handle input errors
    vector_of_scalars(data)

    # Create number to return
    result = 0

    # Iterate over input
    for element in data:
        # Add each element from input to number to return
        result += element
    
    # Convert number to float
    floated_result = float(result)
    return floated_result
예제 #3
0
def column_conversion(vector):
    """
    Converts a row vector into a column vector

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

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list

    Returns
    -------
    column : list of lists of int or float
        List in which each element is a list containing an element from the input vector

    See Also
    --------
    :func:`~regressions.vectors.dimension.single_dimension`

    Notes
    -----
    - Row vector: :math:`\\langle a_1, a_2, \\cdots, a_n \\rangle`
    - Column vector: :math:`\\left\\langle\\begin{matrix} a_1, \\\\ a_2, \\\\ \\cdots, \\\\ a_n \\end{matrix}\\right\\rangle`

    Examples
    --------
    Import `column_conversion` function from `regressions` library
        >>> from regressions.vectors.column import column_conversion
    Convert [1, 2, 3]
        >>> column_3d = column_conversion([1, 2, 3])
        >>> print(column_3d)
        [[1], [2], [3]]
    Convert [-7, 5]
        >>> column_2d = column_conversion([-7, 5])
        >>> print(column_2d)
        [[-7], [5]]
    """
    # Handle input errors
    vector_of_scalars(vector)

    # Create list to return
    result = []

    # Iterate over input
    for element in vector:
        # Store elements as lists within list to return
        result.append([element])

    # Return result
    return result
예제 #4
0
def maximum_value(data):
    """
    Determines the largest value of a data set

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    maximum : int or float
        Largest value from the data set

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

    Notes
    -----
    - Set of numbers: :math:`a_i = \\{ a_1, a_2, \\cdots, a_n \\}`
    - Maximum value of set: :math:`a_{max} \\geq a_j, \\forall a_j \\in a_i`
    - |maximum|

    Examples
    --------
    Import `maximum_value` function from `regressions` library
        >>> from regressions.statistics.maximum import maximum_value
    Determine the maximum of the set [21, 53, 3, 68, 43, 9, 72, 19, 20, 1]
        >>> maximum_even = maximum_value([21, 53, 3, 68, 43, 9, 72, 19, 20, 1])
        >>> print(maximum_even)
        72
    Determine the maximum of the set [12, 81, 13, 8, 42, 72, 91, 20, 20]
        >>> maximum_odd = maximum_value([12, 81, 13, 8, 42, 72, 91, 20, 20])
        >>> print(maximum_odd)
        91
    """
    # Handle input errors
    vector_of_scalars(data)

    # Sort input
    sorted_data = sorted_list(data)

    # Grab last element of sorted input
    result = sorted_data[-1]
    return result
예제 #5
0
def mean_values_integral(equation_type, coefficients, start, end, precision=4):
    """
    Generates a list of all the x-coordinates between two points at which a function's value will equal its average value over that interval

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which an average value must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients of the origianl function under investigation
    start : int or float
        Value of the x-coordinate of the first point to use for evaluating the average value; all results must be greater than this value
    end : int or float
        Value of the x-coordinate of the second point to use for evaluating the average value; all results must be less than this value
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the result

    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 and fourth arguments must be integers or floats
    ValueError
        Third argument must be less than or equal to fourth argument
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    points : list of float or str
        Values of the x-coordinates within the specified interval at which the original function has a value equal to its average value over that entire interval; if the function is sinusoidal, then only the initial results within at most a four-period interval within the specified interval will be listed, but general forms will also be included (however, their results may be outside the specified interval); if the algorithm cannot determine any values, 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`
    - Mean values: :func:`~regressions.analyses.mean_values.average_value_integral`, :func:`~regressions.analyses.mean_values.average_value_derivative`, :func:`~regressions.analyses.mean_values.mean_values_derivative`

    Notes
    -----
    - Mean values for the integral over an interval: :math:`f(c) = \\frac{1}{b - a}\\cdot{\\int_{a}^{b} f(x) \\,dx}` 
    - |mean_integrals|

    Examples
    --------
    Import `mean_values_integral` function from `regressions` library
        >>> from regressions.analyses.mean_values import mean_values_integral
    Generate a list of all the x-coordinates of a cubic function with coefficients 2, 3, 5, and 7 at which the function's value will equal its average value between 10 and 20
        >>> points_cubic = mean_values_integral('cubic', [2, 3, 5, 7], 10, 20)
        >>> print(points_cubic)
        [15.5188]
    Generate a list of all the x-coordinates of a sinusoidal function with coefficients 2, 3, 5, and 7 at which the function's value will equal its average value between 10 and 20
        >>> points_sinusoidal = mean_values_integral('sinusoidal', [2, 3, 5, 7], 10, 20)
        >>> print(points_sinusoidal)
        [10.2503, 11.2689, 12.3447, 13.3633, 14.4391, 15.4577, 16.5335, 17.5521, 18.6279, 19.6465, '10.2503 + 2.0944k', '11.2689 + 2.0944k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    compare_scalars(start, end, 'third', 'fourth')
    positive_integer(precision)

    # Create list to return
    result = []

    # Determine average value of function over interval
    average = average_value_integral(equation_type, coefficients, start, end,
                                     precision)

    # Circumvent division by zero
    if average == 0:
        average = 10**(-precision)

    # Determine points satisfying theorem based on equation type
    if equation_type == 'linear':
        result = linear_roots_initial_value(*coefficients, average, precision)
    elif equation_type == 'quadratic':
        result = quadratic_roots_initial_value(*coefficients, average,
                                               precision)
    elif equation_type == 'cubic':
        result = cubic_roots_initial_value(*coefficients, average, precision)
    elif equation_type == 'hyperbolic':
        result = hyperbolic_roots_initial_value(*coefficients, average,
                                                precision)
    elif equation_type == 'exponential':
        result = exponential_roots_initial_value(*coefficients, average,
                                                 precision)
    elif equation_type == 'logarithmic':
        result = logarithmic_roots_initial_value(*coefficients, average,
                                                 precision)
    elif equation_type == 'logistic':
        result = logistic_roots_initial_value(*coefficients, average,
                                              precision)
    elif equation_type == 'sinusoidal':
        options = sinusoidal_roots_initial_value(*coefficients, average,
                                                 precision)
        result = shifted_points_within_range(options, start, end, precision)

    # Eliminate points outside of interval
    final_result = points_within_range(result, start, end)
    return final_result
예제 #6
0
def average_value_integral(equation_type,
                           coefficients,
                           start,
                           end,
                           precision=4):
    """
    Evaluates the average value of a given function between two points

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which the definite integral must be evaluated (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients of the original function to integrate
    start : int or float
        Value of the x-coordinate of the first point to use for evaluating the average value
    end : int or float
        Value of the x-coordinate of the second point to use for evaluating the average value
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the result

    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 and fourth arguments must be integers or floats
    ValueError
        Third argument must be less than or equal to fourth argument
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    average : float
        Average value of the function between two points; if start and end values are identical, then average value will be zero

    See Also
    --------
    :func:`~regressions.analyses.accumulation.accumulated_area`, :func:`~regressions.analyses.mean_values.mean_values_integral`, :func:`~regressions.analyses.mean_values.average_value_derivative`, :func:`~regressions.analyses.mean_values.mean_values_derivative`

    Notes
    -----
    - Average value of a function over an interval: :math:`f_{avg} = \\frac{1}{b - a}\\cdot{\\int_{a}^{b} f(x) \\,dx}`
    - |mean_integrals|

    Examples
    --------
    Import `average_value_integral` function from `regressions` library
        >>> from regressions.analyses.mean_values import average_value_integral
    Evaluate the average value of a cubic function with coefficients 2, 3, 5, and 7 between end points of 10 and 20
        >>> average_cubic = average_value_integral('cubic', [2, 3, 5, 7], 10, 20)
        >>> print(average_cubic)
        8282.0
    Evaluate the average value of a sinusoidal function with coefficients 2, 3, 5, and 7 between end points of 10 and 20
        >>> average_sinusoidal = average_value_integral('sinusoidal', [2, 3, 5, 7], 10, 20)
        >>> print(average_sinusoidal)
        6.9143
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    compare_scalars(start, end, 'third', 'fourth')
    positive_integer(precision)

    # Determine accumulated value of function over interval
    accumulated_value = accumulated_area(equation_type, coefficients, start,
                                         end, precision)

    # Create intermediary variable
    change = end - start

    # Circumvent division by zero
    if change == 0:
        change = 10**(-precision)

    # Determine average value of function over interval
    ratio = accumulated_value / change

    # Round value
    rounded_ratio = rounded_value(ratio, precision)

    # Return result
    result = rounded_ratio
    return result
예제 #7
0
def average_value_derivative(equation_type,
                             coefficients,
                             start,
                             end,
                             precision=4):
    """
    Evaluates the average rate of change between two points for a given function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which the definite integral must be evaluated (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients of the original function to use for evaluating the average rate of change
    start : int or float
        Value of the x-coordinate of the first point to use for evaluating the rate of change
    end : int or float
        Value of the x-coordinate of the second point to use for evaluating the rate of change
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the result

    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 and fourth arguments must be integers or floats
    ValueError
        Third argument must be less than or equal to fourth argument
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    average : float
        Slope of a function between two points; if start and end values are identical, then slope will be zero

    See Also
    --------
    :func:`~regressions.analyses.mean_values.mean_values_derivative`, 
    :func:`~regressions.analyses.mean_values.average_value_integral`, :func:`~regressions.analyses.mean_values.mean_values_integral`

    Notes
    -----
    - Slope of a function over an interval: :math:`m = \\frac{f(b) - f(a)}{b - a}`
    - |mean_derivatives|

    Examples
    --------
    Import `average_value_derivative` function from `regressions` library
        >>> from regressions.analyses.mean_values import average_value_derivative
    Evaluate the average rate of change of a cubic function with coefficients 2, 3, 5, and 7 between end points of 10 and 20
        >>> average_cubic = average_value_derivative('cubic', [2, 3, 5, 7], 10, 20)
        >>> print(average_cubic)
        1495.0
    Evaluate the average rate of change of a sinusoidal function with coefficients 2, 3, 5, and 7 between end points of 10 and 20
        >>> average_sinusoidal = average_value_derivative('sinusoidal', [2, 3, 5, 7], 10, 20)
        >>> print(average_sinusoidal)
        0.0401
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    compare_scalars(start, end, 'third', 'fourth')
    positive_integer(precision)

    # Create equation 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)

    # Create intermediary variables
    vertical_change = equation(end) - equation(start)
    horizontal_change = end - start

    # Circumvent division by zero
    if horizontal_change == 0:
        horizontal_change = 10**(-precision)

    # Determine average slope
    ratio = vertical_change / horizontal_change
    result = rounded_value(ratio, precision)
    return result
예제 #8
0
def multiple_deviations(actual_array):
    """
    Generates a list of the differences between the actual values from an original list and mean value of the actual values from that original list

    Parameters
    ----------
    actual_array : list of int or float
        List containing the actual values observed from a data set

    Raises
    ------
    TypeError
        Arguments must be 1-dimensional lists
    TypeError
        Elements of arguments must be integers or floats

    Returns
    -------
    deviations : list of float
        List of differences between the actual values and the mean value for all elements from the original list

    See Also
    --------
    :func:`~regressions.statistics.mean.mean_value`, :func:`~regressions.statistics.residuals.multiple_residuals`, :func:`~regressions.statistics.correlation.correlation_coefficient`

    Notes
    -----
    - Observed values: :math:`y_i = \\{ y_1, y_2, \\cdots, y_n \\}`
    - Mean of all observed values: :math:`\\bar{y} = \\frac{1}{n}\\cdot{\\sum\\limits_{i=1}^n y_i}`
    - Deviations: :math:`d_i = \\{ y_1 - \\bar{y}, y_2 - \\bar{y}, \\cdots, y_n - \\bar{y} \\}`
    - |deviation|

    Examples
    --------
    Import `multiple_deviations` function from `regressions` library
        >>> from regressions.statistics.deviations import multiple_deviations
    Generate a list of deviations from this data set [8.2, 9.41, 1.23, 34.7]
        >>> deviations_short = multiple_deviations([8.2, 9.41, 1.23, 34.7])
        >>> print(deviations_short)
        [-5.185000000000002, -3.9750000000000014, -12.155000000000001, 21.315]
    Generate a list of deviations from this data set [5.21, 8.2, 9.41, 1.23, 10.52, 21.76, 34.7]
        >>> deviations_long = multiple_deviations([5.21, 8.2, 9.41, 1.23, 10.52, 21.76, 34.7])
        >>> print(deviations_long)
        [-7.7942857142857145, -4.804285714285715, -3.5942857142857143, -11.774285714285714, -2.484285714285715, 8.755714285714287, 21.69571428571429]
    """
    # Handle input errors
    vector_of_scalars(actual_array)

    # Create list to return
    results = []

    # Calculate mean of input
    average = mean_value(actual_array)

    # Iterate over input
    for element in actual_array:
        # Store deviation of each element in list to return
        results.append(single_deviation(element, average))
    
    # Return results
    return results
예제 #9
0
def median_value(data):
    """
    Determines the median value of a data set

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    median : int or float
        Middle value of the data set, splitting the data evenly in half

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

    Notes
    -----
    - Ordered set of numbers: :math:`a_i = ( a_1, a_2, \\cdots, a_n )`
    - Median of all numbers in set (if set contains an odd amount of numbers): :math:`M = a_{\\lceil n/2 \\rceil}`
    - Median of all numbers in set (if set contains an even amount of numbers): :math:`M = \\frac{a_{n/2} + a_{n/2 + 1}}{2}`
    - |median|

    Examples
    --------
    Import `median_value` function from `regressions` library
        >>> from regressions.statistics.median import median_value
    Determine the median of the set [21, 53, 3, 68, 43, 9, 72, 19, 20, 1]
        >>> median_even = median_value([21, 53, 3, 68, 43, 9, 72, 19, 20, 1])
        >>> print(median_even)
        20.5
    Determine the median of the set [12, 81, 13, 8, 42, 72, 91, 20, 20]
        >>> median_odd = median_value([12, 81, 13, 8, 42, 72, 91, 20, 20])
        >>> print(median_odd)
        20
    """
    # Handle input errors
    vector_of_scalars(data)

    # Sort input
    sorted_data = sorted_list(data)

    # Determine length of input
    length = len(sorted_data)

    # Handle an even amount of elements
    if length % 2 == 0:
        upper_index = int(length / 2)
        lower_index = int(upper_index - 1)
        upper_value = sorted_data[upper_index]
        lower_value = sorted_data[lower_index]
        result = (upper_value + lower_value) / 2
        return result

    # Handle an odd amount of elements
    else:
        index = int(floor(length / 2))
        result = sorted_data[index]
        return result
예제 #10
0
def vector_magnitude(vector):
    """
    Calculates the magnitude of a vector

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

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    magnitude : float
        Measure of the size of the vector, as determined by taking the root of the sum of the squares of its components

    See Also
    --------
    :func:`~regressions.vectors.components.component_form`, :func:`~regressions.vectors.direction.vector_direction`,
    :func:`~regressions.vectors.unit.unit_vector`

    Notes
    -----
    - Vector: :math:`\\mathbf{a} = \\langle a_1, a_2, \\cdots, a_n \\rangle`
    - Magnitude of vector: :math:`\\|\\mathbf{a}\\| = \\sqrt{a_1^2 + a_2^2 + \\cdots + a_n^2}`
    - |magnitude|

    Examples
    --------
    Import `vector_magnitude` function from `regressions` library
        >>> from regressions.vectors.magnitude import vector_magnitude
    Determine the magnitude of the vector with components [7, 5, -1]
        >>> magnitude_3d = vector_magnitude([7, 5, -1])
        >>> print(magnitude_3d)
        8.660254037844387
    Determine the magnitude of the vector with components [3, 2]
        >>> magnitude_2d = vector_magnitude([3, 2])
        >>> print(magnitude_2d)
        3.605551275463989
    """
    # Handle input errors
    vector_of_scalars(vector)

    # Create intermediary list
    squares = []

    # Iterate over input
    for element in vector:
        # Store squares of each element in intermediary list
        squares.append(element**2)

    # Add all squares in list
    sum_squares = sum_value(squares)

    # Take the square root of the sum of all squares
    result = sum_squares**(1 / 2)
    return result
예제 #11
0
 def test_vector_scalars_multitype_raises(self):
     with self.assertRaises(Exception) as context:
         vector_of_scalars(good_multitype)
     self.assertEqual(type(context.exception), TypeError)
     self.assertEqual(str(context.exception),
                      'Elements of argument must be integers or floats')
예제 #12
0
def half(data):
    """
    Splits an unsorted data set into two sorted data sets, each containing the same amount of elements (in sets with an odd amount of elements, the median is not included in either half)

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze
    
    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    sections['upper'] : list of int or float
        List of all elements from the upper half of a sorted data set
    sections['lower'] : list of int or float
        List of all elements from the lower half of a sorted data set

    See Also
    --------
    :func:`~regressions.statistics.sort.sorted_list`

    Notes
    -----
    - Set of numbers: :math:`a_i = \\{ a_1, a_2, \\cdots, a_n \\}`
    - Sorted version of set: :math:`A_i = ( A_1, A_2, \\cdots, A_n )`

        - For all terms in :math:`A_i`: :math:`A_{n-1} \\leq A_n`

    - For sets with an odd amount of numbers:

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

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

    Examples
    --------
    Import `half` function from `regressions` library
        >>> from regressions.statistics.halve import half
    Determine the sorted upper half of the set [5, 2, 9, 8]
        >>> sections_short = half([5, 2, 9, 8])
        >>> print(sections_short['upper'])
        [8, 9]
    Determine the sorted lower half of the set [11, 3, 52, 25, 21, 25, 6]
        >>> sections_long = half([11, 3, 52, 25, 21, 25, 6])
        >>> print(sections_long['lower'])
        [3, 6, 11]
    """
    # Handle input errors
    vector_of_scalars(data)

    # Sort input
    sorted_data = sorted_list(data)

    # Partition sorted data
    result = partition(sorted_data)
    return result
예제 #13
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
예제 #14
0
def accumulated_area(equation_type, coefficients, start, end, precision=4):
    """
    Evaluates the definite integral between two points for a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which the definite integral must be evaluated (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients of the original function to integrate
    start : int or float
        Value of the x-coordinate of the first point to use for evaluating the definite integral
    end : int or float
        Value of the x-coordinate of the second point to use for evaluating the definite integral
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the result

    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 and fourth arguments must be integers or floats
    ValueError
        Third argument must be less than or equal to fourth argument
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    area : float
        Definite integral of the original equation, evaluated between two points; if start and end values are identical, then definite integral will be zero

    See Also
    --------
    :func:`~regressions.analyses.integrals.linear.linear_integral`, :func:`~regressions.analyses.integrals.quadratic.quadratic_integral`, :func:`~regressions.analyses.integrals.cubic.cubic_integral`, :func:`~regressions.analyses.integrals.hyperbolic.hyperbolic_integral`, :func:`~regressions.analyses.integrals.exponential.exponential_integral`, :func:`~regressions.analyses.integrals.logarithmic.logarithmic_integral`, :func:`~regressions.analyses.integrals.logistic.logistic_integral`, :func:`~regressions.analyses.integrals.sinusoidal.sinusoidal_integral`

    Notes
    -----
    - Definite integral of a function: :math:`\\int_{a}^{b} f(x) \\,dx = F(b) - F(a)`
    - |definite_integral|
    - |fundamental_theorem|

    Examples
    --------
    Import `accumulated_area` function from `regressions` library
        >>> from regressions.analyses.accumulation import accumulated_area
    Evaluate the definite integral of a linear function with coefficients 2 and 3 between the end points 10 and 20
        >>> area_linear = accumulated_area('linear', [2, 3], 10, 20)
        >>> print(area_linear)
        330.0
    Evaluate the definite integral of a cubic function with coefficients 8, 6, -10, and 7 between the end points 10 and 20
        >>> area_cubic = accumulated_area('cubic', [8, 6, -10, 7], 10, 20)
        >>> print(area_cubic)
        312570.0
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    compare_scalars(start, end, 'third', 'fourth')
    positive_integer(precision)

    # Create indefinite integral based on equation type
    integral = lambda x: x
    if equation_type == 'linear':
        integral = linear_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'quadratic':
        integral = quadratic_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'cubic':
        integral = cubic_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'hyperbolic':
        integral = hyperbolic_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'exponential':
        integral = exponential_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'logarithmic':
        integral = logarithmic_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'logistic':
        integral = logistic_integral(*coefficients, precision)['evaluation']
    elif equation_type == 'sinusoidal':
        integral = sinusoidal_integral(*coefficients, precision)['evaluation']

    # Evaluate definite integral
    area = integral(end) - integral(start)

    # Round evaluation
    result = rounded_value(area, precision)
    return result
예제 #15
0
def inflection_points(equation_type, coefficients, precision=4):
    """
    Calculates the inflection points of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which inflections must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    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
        Last argument must be a positive integer

    Returns
    -------
    points : list of float or str
        Values of the x-coordinates at which the original function has an inflection point; 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 function has no inflection 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.criticals.critical_points`, :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.points.key_coordinates`

    Notes
    -----
    - Critical points for the second derivative of a function: :math:`c_i = \\{ c_1, c_2, c_3,  \\cdots, c_{n-1}, c_n \\}`
    - X-coordinates of the inflections of the function: :math:`x_{infl} = \\{ x \\mid x \\in c_i, \\left( f''(\\frac{c_{j-1} + c_j}{2}) < 0 \\cap f''(\\frac{c_j + c_{j+1}}{2}) > 0 \\right) \\\\ \\cup \\left( f''(\\frac{c_{j-1} + c_j}{2}) > 0 \\cap f''(\\frac{c_j + c_{j+1}}{2}) < 0 \\right) \\}`
    - |inflection_points|

    Examples
    --------
    Import `inflection_points` function from `regressions` library
        >>> from regressions.analyses.inflections import inflection_points
    Calculate the inflection points of a cubic functions with coefficients 1, -15, 63, and -7
        >>> points_cubic = inflection_points('cubic', [1, -15, 63, -7])
        >>> print(points_cubic)
        [5.0]
    Calculate the inflection points of a sinusoidal functions with coefficients 2, 3, 5, and 7
        >>> points_sinusoidal = inflection_points('sinusoidal', [2, 3, 5, 7])
        >>> print(points_sinusoidal)
        [5.0, 6.0472, 7.0944, 8.1416, 9.1888, '5.0 + 1.0472k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)

    # Create sign chart
    intervals_set = sign_chart(equation_type, coefficients, 2, precision)

    # Handle hyperbolic case
    if equation_type == 'hyperbolic':
        result = [None]
        return result

    # Determine inflections
    result = []
    for i in range(len(intervals_set)):
        try:
            if (intervals_set[i] == 'positive' and intervals_set[i + 2]
                    == 'negative') or (intervals_set[i] == 'negative'
                                       and intervals_set[i + 2] == 'positive'):
                result.append(intervals_set[i + 1])
        except IndexError:
            pass

    # Handle sinusoidal case
    if equation_type == 'sinusoidal':
        result.append(intervals_set[-1])

    # Handle no inflections
    if len(result) == 0:
        result.append(None)
    return result
예제 #16
0
def five_number_summary(data, precision=4):
    """
    Calculates the five number summary of a given data set: minimum, first quartile, median, third quartile, and maximum

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the result

    Raises
    ------
    TypeError
        First argument must be a 1-dimensional list
    TypeError
        Elements of first argument must be integers or floats
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    summary['minimum'] : float
        Smallest value from the data set
    summary['q1'] : float
        First quartile of the data set, below which 25% of the data fall
    summary['median'] : float
        Middle value of the data set, splitting the data evenly in half
    summary['q3'] : float
        Third quartile of the data set, above which 25% of the data fall
    summary['maximum'] : float
        Largest value from the data set

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

    Notes
    -----
    - Set of numbers: :math:`a_i = \\{ a_1, a_2, \\cdots, a_n \\}`
    - Minimum: :math:`a_{min} \\leq a_j, \\forall a_j \\in a_i`
    - Maximum: :math:`a_{max} \\geq a_j, \\forall a_j \\in a_i`
    - For sets with an odd amount of numbers:
        
        - First quartile: :math:`Q_1 = a_{\\lceil n/4 \\rceil}`
        - Median: :math:`M = 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}`
            - Median: :math:`M = \\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}`
            - Median: :math:`M = \\frac{a_{n/2} + a_{n/2 + 1}}{2}`
            - Third quartile: :math:`Q_3 = \\frac{a_{3n/4} + a_{3n/4 + 1}}{2}`

    - |five_number_summary|

    Examples
    --------
    Import `five_number_summary` function from `regressions` library
        >>> from regressions.statistics.summary import five_number_summary
    Determine the five number summary of the set [21, 53, 3, 68, 43, 9, 72, 19, 20, 1]
        >>> summary_even = five_number_summary([21, 53, 3, 68, 43, 9, 72, 19, 20, 1])
        >>> print(summary_even['q1'])
        9.0
        >>> print(summary_even['maximum'])
        72.0
    Determine the five number summary of the set [12, 81, 13, 8, 42, 72, 91, 20, 20]
        >>> summary_odd = five_number_summary([12, 81, 13, 8, 42, 72, 91, 20, 20])
        >>> print(summary_odd['q3'])
        76.5
        >>> print(summary_odd['minimum'])
        8.0
    """
    # Handle input errors
    vector_of_scalars(data, 'first')
    positive_integer(precision)

    # Calculate all values used in five-number summary
    min_value = minimum_value(data)
    q1 = quartile_value(data, 1)
    median = median_value(data)
    q3 = quartile_value(data, 3)
    max_value = maximum_value(data)

    # Round all values
    rounded_min = rounded_value(min_value, precision)
    rounded_q1 = rounded_value(q1, precision)
    rounded_med = rounded_value(median, precision)
    rounded_q3 = rounded_value(q3, precision)
    rounded_max = rounded_value(max_value, precision)

    # Package values in single dictionary to return
    result = {
        'minimum': rounded_min,
        'q1': rounded_q1,
        'median': rounded_med,
        'q3': rounded_q3,
        'maximum': rounded_max
    }
    return result
예제 #17
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
예제 #18
0
 def test_vector_scalars_final_string_raises(self):
     with self.assertRaises(Exception) as context:
         vector_of_scalars(bad_vector_final_string)
     self.assertEqual(type(context.exception), TypeError)
     self.assertEqual(str(context.exception),
                      'Elements of argument must be integers or floats')
예제 #19
0
def average_values(equation_type, coefficients, start, end, precision=4):
    """
    Calculates the average values for a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which average values must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients of the origianl function under investigation
    start : int or float
        Value of the x-coordinate of the first point to use for evaluating the average values; results within lists must be greater than this value
    end : int or float
        Value of the x-coordinate of the second point to use for evaluating the average values; results within lists must be less than this value
    precision : int, default=4
        Maximum number of digits that can appear after the decimal place of the result

    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 and fourth arguments must be integers or floats
    ValueError
        Third argument must be less than or equal to fourth argument
    ValueError
        Last argument must be a positive integer

    Returns
    -------
    averages['average_value_derivative'] : float
        Slope of a function between two points
    averages['mean_values_derivative'] : list of float or str
        Values of the x-coordinates within the specified interval at which the original function has a value equal to its average value over that entire interval; if the function is sinusoidal, then only the initial results within at most a four-period interval within the specified interval will be listed, but general forms will also be included (however, their results may be outside the specified interval); if the algorithm cannot determine any values, then it will return a list of `None`
    averages['average_value_integral'] : float
        Average value of the function between two points
    averages['mean_values_integral'] : list of float or str
        Values of the x-coordinates within the specified interval at which the original function has a value equal to its average value over that entire interval; if the function is sinusoidal, then only the initial results within at most a four-period interval within the specified interval will be listed, but general forms will also be included (however, their results may be outside the specified interval); if the algorithm cannot determine any values, then it will return a list of `None`

    See Also
    --------
    :func:`~regressions.analyses.mean_values.average_value_derivative`, :func:`~regressions.analyses.mean_values.mean_values_derivative`, :func:`~regressions.analyses.mean_values.average_value_integral`, :func:`~regressions.analyses.mean_values.mean_values_integral`

    Notes
    -----
    - |mean_derivatives|
    - |mean_integrals|

    Examples
    --------
    Import `average_values` function from `regressions` library
        >>> from regressions.analyses.mean_values import average_values
    Calculate the averages of a cubic function with coefficients 2, 3, 5, and 7 between 10 and 20
        >>> averages_cubic = average_values('cubic', [2, 3, 5, 7], 10, 20)
        >>> print(averages_cubic['average_value_derivative'])
        1495.0
        >>> print(averages_cubic['mean_values_derivative'])
        [15.2665]
        >>> print(averages_cubic['average_value_integral'])
        8282.0
        >>> print(averages_cubic['mean_values_integral'])
        [15.5188]
    Calculate the averages of a sinusoidal function with coefficients 2, 3, 5, and 7 between 10 and 20
        >>> averages_sinusoidal = average_values('sinusoidal', [2, 3, 5, 7], 10, 20)
        >>> print(averages_sinusoidal['average_value_derivative'])
        0.0401
        >>> print(averages_sinusoidal['mean_values_derivative'])
        [10.7618, 11.8046, 12.8562, 13.899, 14.9506, 15.9934, 17.045, 18.0878, 19.1394, '10.7618 + 2.0944k', '11.8046 + 2.0944k']
        >>> print(averages_sinusoidal['average_value_integral'])
        6.9143
        >>> print(averages_sinusoidal['mean_values_integral'])
        [10.2503, 11.2689, 12.3447, 13.3633, 14.4391, 15.4577, 16.5335, 17.5521, 18.6279, 19.6465, '10.2503 + 2.0944k', '11.2689 + 2.0944k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    compare_scalars(start, end, 'third', 'fourth')
    positive_integer(precision)

    # Determine various mean values
    derivative_value = average_value_derivative(equation_type, coefficients,
                                                start, end, precision)
    derivative_inputs = mean_values_derivative(equation_type, coefficients,
                                               start, end, precision)
    integral_value = average_value_integral(equation_type, coefficients, start,
                                            end, precision)
    integral_inputs = mean_values_integral(equation_type, coefficients, start,
                                           end, precision)

    # Package all values in single dictionary
    results = {
        'average_value_derivative': derivative_value,
        'mean_values_derivative': derivative_inputs,
        'average_value_integral': integral_value,
        'mean_values_integral': integral_inputs
    }
    return results
예제 #20
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
예제 #21
0
def intercept_points(equation_type, coefficients, precision=4):
    """
    Calculates the roots of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which intercepts must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    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
        Last argument must be a positive integer

    Returns
    -------
    points : list of float or str
        Values of the x-coordinates at which the original function crosses the x-axis; if the function is sinusoidal, then only the initial results within a four-period interval will be listed, but general forms will also be included; if the function has no x-intercepts, 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.criticals.critical_points`, :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 \\}`
    - X-intercepts (roots) of the function: :math:`x_r = \\{ r \\mid r \\in x_i, f(r) = 0 \\}`
    - |intercepts|

    Examples
    --------
    Import `intercept_points` function from `regressions` library
        >>> from regressions.analyses.intercepts import intercept_points
    Calculate the roots of a cubic function with coefficients 1, -15, 66, and -80
        >>> points_cubic = intercept_points('cubic', [1, -15, 66, -80])
        >>> print(points_cubic)
        [2.0, 5.0, 8.0]
    Calculate the roots of a sinusoidal function with coefficients 3, 1, -2, and 3
        >>> points_sinusoidal = intercept_points('sinusoidal', [3, 1, -2, 3])
        >>> print(points_sinusoidal)
        [-3.5708, 2.7124, 8.9956, 15.2788, 21.5619, '-3.5708 + 6.2832k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)

    # Determine intercepts based on equation type
    result = []
    if equation_type == 'linear':
        result = linear_roots(*coefficients, precision)
    elif equation_type == 'quadratic':
        result = quadratic_roots(*coefficients, precision)
    elif equation_type == 'cubic':
        result = cubic_roots(*coefficients, precision)
    elif equation_type == 'hyperbolic':
        result = hyperbolic_roots(*coefficients, precision)
    elif equation_type == 'exponential':
        result = exponential_roots(*coefficients, precision)
    elif equation_type == 'logarithmic':
        result = logarithmic_roots(*coefficients, precision)
    elif equation_type == 'logistic':
        result = logistic_roots(*coefficients, precision)
    elif equation_type == 'sinusoidal':
        result = sinusoidal_roots(*coefficients, precision)
    return result
예제 #22
0
def unit_vector(vector):
    """
    Calculates the unit vector corresponding to a given vector (and therefore having the same direction)

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

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    unit : list of float
        Vector with a magnitue of 1 in the same direction as the original vector

    See Also
    --------
    :func:`~regressions.vectors.components.component_form`, :func:`~regressions.vectors.multiplication.scalar_product_vector`, :func:`~regressions.vectors.direction.vector_direction`,
    :func:`~regressions.vectors.magnitude.vector_magnitude`

    Notes
    -----
    - Comparison vector: :math:`\\mathbf{a} = \\langle a_1, a_2, \\cdots, a_n \\rangle`
    - Unit vector with same direction: :math:`\\mathbf{u}= \\frac{\\mathbf{a}}{\\|\\mathbf{a}\\|}`
    - |unit_vector|

    Examples
    --------
    Import `unit_vector` function from `regressions` library
        >>> from regressions.vectors.unit import unit_vector
    Determine the unit vector of the vector with components [7, 5, -1]
        >>> unit_3d = unit_vector([7, 5, -1])
        >>> print(unit_3d)
        [0.8082903768654759, 0.5773502691896257, -0.11547005383792514]
    Determine the unit vector of the vector with components [3, 2]
        >>> unit_2d = unit_vector([3, 2])
        >>> print(unit_2d)
        [0.8320502943378437, 0.5547001962252291]
    """
    # Handle input errors
    vector_of_scalars(vector)

    # Determine magnitude of input
    magnitude = vector_magnitude(vector)

    # Circumvent division by zero
    if magnitude == 0:
        magnitude = 0.0001

    # Calculate reciprocal of magnitude
    reciprocal_magnitude = 1 / magnitude

    # Multiply input by the reciprocal of its magnitude
    result = scalar_product_vector(vector, reciprocal_magnitude)
    return result
예제 #23
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
예제 #24
0
 def test_vector_scalars_4long(self):
     vector_scalars_4long = vector_of_scalars(longer_vector)
     self.assertEqual(
         vector_scalars_4long,
         'Argument is a 1-dimensional list containing elements that are integers or floats'
     )
예제 #25
0
def key_coordinates(equation_type, coefficients, precision = 4):
    """
    Calculates the key points of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which key points must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    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
        Last argument must be a positive integer

    Returns
    -------
    points['roots'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has a root; second elements of those lists will be 0; if the function is sinusoidal, then only the initial results within a four-period interval will be listed, but general forms will also be included; if the function has no roots, then it will return a list of `None`
    points['maxima'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has a relative maximum; second elements of those lists will be the y-coordinate of that maximum; if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form will also be included; if the function has no maxima, then it will return a list of `None`
    points['minima'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has a relative minimum; second elements of those lists will be the y-coordinate of that minimum; if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form will also be included; if the function has no minima, then it will return a list of `None`
    points['inflections'] : list of float or str
        List containing two-element lists for each point; first elements of those lists will be the value of the x-coordinate at which the original function has an inflection; second elements of those lists will be the y-coordinate of that inflection; if the function is sinusoidal, then only the initial results within a two-period interval will be listed, but a general form will also be included; if the function has no inflection 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.criticals.critical_points`, :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.maxima.maxima_points`, :func:`~regressions.analyses.minima.minima_points`, :func:`~regressions.analyses.extrema.extrema_points`, :func:`~regressions.analyses.inflections.inflection_points`

    Notes
    -----
    - Key points include x-intercepts, maxima, minima, and points of inflection
    - |intercepts|
    - |extrema|
    - |inflections|

    Examples
    --------
    Import `key_coordinates` function from `regressions` library
        >>> from regressions.analyses.points import key_coordinates
    Calculate the key points of a cubic function with coefficients 1, -15, 63, and -7
        >>> points_cubic = key_coordinates('cubic', [1, -15, 63, -7])
        >>> print(points_cubic['roots'])
        [[0.1142, 0.0]]
        >>> print(points_cubic['maxima'])
        [[3.0, 74.0]]
        >>> print(points_cubic['minima'])
        [[7.0, 42.0]]
        >>> print(points_cubic['inflections'])
        [[5.0, 58.0]]
    Calculate the key points of a sinusoidal function with coefficients 2, 3, 5, and 1
        >>> points_sinusoidal = key_coordinates('sinusoidal', [2, 3, 5, 1])
        >>> print(points_sinusoidal['roots'])
        [[4.8255, 0.0], [6.2217, 0.0], [6.9199, 0.0], [8.3161, 0.0], [9.0143, 0.0], [10.4105, 0.0], [11.1087, 0.0], [12.5049, 0.0], [13.203, 0.0], [14.5993, 0.0], ['4.8255 + 2.0944k', 0.0], ['6.2217 + 2.0944k', 0.0]]
        >>> print(points_sinusoidal['maxima'])
        [[5.5236, 3.0], [7.618, 3.0], [9.7124, 3.0], ['5.5236 + 2.0944k', 3.0]]
        >>> print(points_sinusoidal['minima'])
        [[6.5708, -1.0], [8.6652, -1.0], ['6.5708 + 2.0944k', -1.0]]
        >>> print(points_sinusoidal['inflections'])
        [[5.0, 1.0], [6.0472, 1.0], [7.0944, 1.0], [8.1416, 1.0], [9.1888, 1.0001], ['5.0 + 1.0472k', 1.0]]
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)
    
    # Create lists of inputs
    intercepts_inputs = intercept_points(equation_type, coefficients, precision)
    extrema_inputs = extrema_points(equation_type, coefficients, precision)
    maxima_inputs = extrema_inputs['maxima']
    minima_inputs = extrema_inputs['minima']
    inflections_inputs = inflection_points(equation_type, coefficients, precision)

    # Generate coordinate pairs for all x-intercepts
    intercepts_coordinates = coordinate_pairs(equation_type, coefficients, intercepts_inputs, 'intercepts', precision)
    
    # Generate coordinate pairs for all maxima
    maxima_coordinates = coordinate_pairs(equation_type, coefficients, maxima_inputs, 'maxima', precision)
    
    # Generate coordinate pairs for all minima
    minima_coordinates = coordinate_pairs(equation_type, coefficients, minima_inputs, 'minima', precision)
    
    # Generate coordinate pairs for all points of inflection
    inflections_coordinates = coordinate_pairs(equation_type, coefficients, inflections_inputs, 'inflections', precision)
    
    # Create dictionary to return
    result = {
        'roots': intercepts_coordinates,
        'maxima': maxima_coordinates,
        'minima': minima_coordinates,
        'inflections': inflections_coordinates
    }
    return result
예제 #26
0
def minima_points(equation_type, coefficients, precision = 4):
    """
    Calculates the minima of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which the minima must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    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
        Last argument must be a positive integer

    Returns
    -------
    points : list of float
        Values of the x-coordinates at which the original function has a relative minimum; if the function is sinusoidal, then only two or three results within a two-period interval will be listed; if the function has no minima, 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.criticals.critical_points`, :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.maxima.maxima_points`, :func:`~regressions.analyses.extrema.extrema_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 \\}`
    - X-coordinates of the minima of the function: :math:`x_{min} = \\{ x \\mid x \\in c_i, f'(\\frac{c_{j-1} + c_j}{2}) < 0, f'(\\frac{c_j + c_{j+1}}{2}) > 0 \\}`
    - |minima_values|

    Examples
    --------
    Import `minima_points` function from `regressions` library
        >>> from regressions.analyses.minima import minima_points
    Calculate the minima of a cubic function with coefficients 1, -15, 63, and -7
        >>> points_cubic = minima_points('cubic', [1, -15, 63, -7])
        >>> print(points_cubic)
        [7.0]
    Calculate the minima of a sinusoidal function with coefficients 2, 3, 5, and 7
        >>> points_sinusoidal = minima_points('sinusoidal', [2, 3, 5, 7])
        >>> print(points_sinusoidal)
        [6.5708, 8.6652]
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)
    
    # Create sign chart
    intervals = sign_chart(equation_type, coefficients, 1, precision)
    
    # Determine minima
    result = []
    for i in range(len(intervals)):
        try:
            if intervals[i] == 'negative' and intervals[i + 2] == 'positive':
                result.append(intervals[i + 1])
        except IndexError:
            pass
    
    # Handle no minima
    if len(result) == 0:
        result.append(None)
    return result
예제 #27
0
def vector_direction(vector):
    """
    Calculates the direction of a vector in radians and degrees

    Parameters
    ----------
    vector : list of int or float
        List of two numbers representing a vector, in which the first number is the horizontal component and the second is the vertical component

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats
    ValueError
        Argument must contain exactly two elements

    Returns
    -------
    direction['radian'] : float
        Measure of the angle of the vector in radians
    direction['degree'] : float
        Measure of the angle of the vector in degrees

    See Also
    --------
    :func:`~regressions.vectors.components.component_form`, :func:`~regressions.vectors.magnitude.vector_magnitude`, :func:`~regressions.vectors.unit.unit_vector`

    Notes
    -----
    - Vector: :math:`\\langle x, y \\rangle`
    - Direction of vector: :math:`\\theta = \\tan^{-1}(\\frac{y}{x})`
    - |direction|

    Examples
    --------
    Import `vector_direction` function from `regressions` library
        >>> from regressions.vectors.direction import vector_direction
    Determine the direction of a vector with a component form of [7, 5]
        >>> direction_positive = vector_direction([7, 5])
        >>> print(direction_positive['radian'])
        0.6202494859828215
        >>> print(direction_positive['degree'])
        35.53767779197438
    Determine the direction of a vector with a component form of [-3, 11]
        >>> direction_negative = vector_direction([-3, 11])
        >>> print(direction_negative['radian'])
        -1.3045442776439713
        >>> print(direction_negative['degree'])
        -74.74488129694222
    """
    # Handle input errors
    vector_of_scalars(vector)
    length(vector, 2)

    # Circumvent division by zero
    if vector[0] == 0:
        vector[0] = 0.0001
    
    # Create intermediary variable
    ratio = vector[1] / vector[0]
    
    # Determine direction in radians
    radian_measure = atan(ratio)

    # Convert radians into degrees
    degree_measure = degrees(radian_measure)
    
    # Package both measures in single dictionary
    result = {
        'radian': radian_measure,
        'degree': degree_measure
    }
    return result
예제 #28
0
def range_value(data):
    """
    Determines the range of a data set (i.e., the difference between its largest value and its smallest value)

    Parameters
    ----------
    data : list of int or float
        List of numbers to analyze

    Raises
    ------
    TypeError
        Argument must be a 1-dimensional list
    TypeError
        Elements of argument must be integers or floats

    Returns
    -------
    interval : float
        Range of data set

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

    Notes
    -----
    - Set of numbers: :math:`a_i = \\{ a_1, a_2, \\cdots, a_n \\}`
    - Range of set: :math:`R = a_{max} - a_{min}`
    
        - :math:`a_{min} \\leq a_j, \\forall a_j \\in a_i`
        - :math:`a_{max} \\geq a_j, \\forall a_j \\in a_i`

    - |range|

    Examples
    --------
    Import `range_value` function from `regressions` library
        >>> from regressions.statistics.ranges import range_value
    Determine the range of the set [21, 53, 3, 68, 43, 9, 72, 19, 20, 1]
        >>> range_even = range_value([21, 53, 3, 68, 43, 9, 72, 19, 20, 1])
        >>> print(range_even)
        71.0
    Determine the range of the set [12, 81, 13, 8, 42, 72, 91, 20, 20]
        >>> range_odd = range_value([12, 81, 13, 8, 42, 72, 91, 20, 20])
        >>> print(range_odd)
        83.0
    """
    # Handle input errors
    vector_of_scalars(data)

    # Determine maximum and minimum of input
    max_value = maximum_value(data)
    min_value = minimum_value(data)

    # Calculate difference between maximum and minimum
    difference = max_value - min_value

    # Convert difference to float
    result = float(difference)
    return result
예제 #29
0
def extrema_points(equation_type, coefficients, precision=4):
    """
    Calculates the extrema of a specific function

    Parameters
    ----------
    equation_type : str
        Name of the type of function for which extrema must be determined (e.g., 'linear', 'quadratic')
    coefficients : list of int or float
        Coefficients to use to generate the equation to investigate
    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
        Last argument must be a positive integer

    Returns
    -------
    points['maxima'] : list of float or str
        Values of the x-coordinates at which the original function has a relative maximum; if the function is sinusoidal, then only two or three results within a two-period interval will be listed, but a general form will also be included; if the function has no maxima, then it will return a list of `None`
    points['minima'] : list of float or str
        Values of the x-coordinates at which the original function has a relative minimum; if the function is sinusoidal, then only two or three results within a two-period interval will be listed, but a general form will also be included; if the function has no minima, 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.criticals.critical_points`, :func:`~regressions.analyses.intervals.sign_chart`, :func:`~regressions.analyses.maxima.maxima_points`, :func:`~regressions.analyses.minima.minima_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 \\}`
    - X-coordinates of the extrema of the function: :math:`x_{ext} = \\{ x \\mid x \\in c_i, \\left( f'(\\frac{c_{j-1} + c_j}{2}) < 0 \\cap f'(\\frac{c_j + c_{j+1}}{2}) > 0 \\right) \\\\ \\cup \\left( f'(\\frac{c_{j-1} + c_j}{2}) > 0 \\cap f'(\\frac{c_j + c_{j+1}}{2}) < 0 \\right) \\}`
    - |extrema_values|

    Examples
    --------
    Import `extrema_points` function from `regressions` library
        >>> from regressions.analyses.extrema import extrema_points
    Calulate the extrema of a cubic function with coefficients 1, -15, 63, and -7
        >>> points_cubic = extrema_points('cubic', [1, -15, 63, -7])
        >>> print(points_cubic['maxima'])
        [3.0]
        >>> print(points_cubic['minima'])
        [7.0]
    Calulate the extrema of a sinusoidal function with coefficients 2, 3, 5, and 7
        >>> points_sinusoidal = extrema_points('sinusoidal', [2, 3, 5, 7])
        >>> print(points_sinusoidal['maxima'])
        [5.5236, 7.618, 9.7124, '5.5236 + 2.0944k']
        >>> print(points_sinusoidal['minima'])
        [6.5708, 8.6652, '6.5708 + 2.0944k']
    """
    # Handle input errors
    select_equations(equation_type)
    vector_of_scalars(coefficients, 'second')
    positive_integer(precision)

    # Determine maxima and minima
    max_points = maxima_points(equation_type, coefficients, precision)
    min_points = minima_points(equation_type, coefficients, precision)

    # Create dictionary to return
    result = {}

    # Handle sinusoidal case
    if equation_type == 'sinusoidal':
        # Recreate sign chart
        intervals_set = sign_chart('sinusoidal', coefficients, 1, precision)

        # Grab general form
        general_form = intervals_set[-1]

        # Extract periodic unit
        periodic_unit_index = general_form.find(' + ') + 3
        periodic_unit = 2 * float(general_form[periodic_unit_index:-1])
        rounded_periodic_unit = rounded_value(periodic_unit, precision)

        # Create general forms for max and min
        max_general_form = str(
            max_points[0]) + ' + ' + str(rounded_periodic_unit) + 'k'
        min_general_form = str(
            min_points[0]) + ' + ' + str(rounded_periodic_unit) + 'k'

        # Append general form as final element of each list
        max_extended = max_points + [max_general_form]
        min_extended = min_points + [min_general_form]
        result = {'maxima': max_extended, 'minima': min_extended}

    # Handle all other cases
    else:
        result = {'maxima': max_points, 'minima': min_points}
    return result
예제 #30
0
def scalar_product_vector(vector, scalar):
    """
    Calculates the product of a vector and a scalar

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

    Raises
    ------
    TypeError
        First argument must be a 1-dimensional list
    TypeError
        Elements of first argument must be integers or floats
    TypeError
        Second argument must be an integer or a float

    Returns
    -------
    product : list of int or float
        List of numbers in which each element is the product of the scalar factor and the corresponding element from the input vector

    See Also
    --------
    :func:`~regressions.matrices.multiplication.scalar_product_matrix`, :func:`~regressions.vectors.addition.vector_sum`

    Notes
    -----
    - Vector: :math:`\\mathbf{a} = \\langle a_1, a_2, \\cdots, a_n \\rangle`
    - Scalar: :math:`c`
    - Scalar product: :math:`c\\cdot{\\mathbf{a}} = \\langle c\\cdot{a_1}, c\\cdot{a_2}, \\cdots, c\\cdot{a_n} \\rangle`
    - |scalar_multiplication|

    Examples
    --------
    Import `scalar_product_vector` function from `regressions` library
        >>> from regressions.vectors.multiplication import scalar_product_vector
    Multiply [1, 2, 3] and -2
        >>> product_3d = scalar_product_vector([1, 2, 3], -2)
        >>> print(product_3d)
        [-2, -4, -6]
    Multiply [-5, 12] and 3
        >>> product_2d = scalar_product_vector([-5, 12], 3)
        >>> print(product_2d)
        [-15, 36]
    """
    # Handle input errors
    vector_of_scalars(vector, 'first')
    scalar_value(scalar, 'second')

    # Create list to return
    result = []

    # Iterate over input
    for element in vector:
        # Store products in list to return
        result.append(element * scalar)

    # Return result
    return result