Search code examples
pythonstatisticsdistributionexponential-distributiondata-transform

Exponential distribution of values between a given range in Python


I have three variables Min=0.29, Max=6.52 and center = 2.10. I wish to create a table that distributes this data into 100 values in a table format in the following fashion:

enter image description here

Here, this image can be split into two parts 0 to 50 and 50 to 100.

In the first part, the increase in x vs y for subsequent value is higher between 1-10 vs 10-20 and higher in 10-20 vs 20-30 and so on.

In the second part, the increase in x vs y for subsequent value is lower between 50-60 vs 60-70 and lower between 60-70 vs 70-80 and so on.

Now, I don't have high proficiency in statistics hence was unable to figure out how to provide min, max and centre value to an exponential distribution and how to implement it in python.

I tried using solution given in link, but couldn't get it to work for my case. Any help will be appreciated.


Solution

  • Each of the two exponential functions is defined by 3 parameters, but you only have 2 points belonging to each. One possibility is to provide the asymptotic value for both functions. I'll paste my code here, including the derivation of all formulae, for lack of time – sorry:

    from math import exp, log
    from matplotlib import pyplot as plt
    
    X_MIN, X_CTR, X_MAX = 1, 50, 100
    Y_MIN, Y_CTR, Y_MAX = 0.29, 2.10, 6.52
    
    c1 = float(input(f"c1 (> {Y_CTR}): "))
    c2 = float(input(f"c2 (< {Y_CTR}): "))
    plot = input("plot? (y|n): ")[:1] in "yY"
    
    # c1 - a1 * exp(-b1 * X_MIN) == Y_MIN  # with a1 > 0, b1 > 0, c1 > Y_CTR
    # c1 - a1 * exp(-b1 * X_CTR) == Y_CTR
    # c2 + a2 * exp( b2 * X_CTR) == Y_CTR  # with a2 > 0, b2 > 0, c2 < Y_CTR
    # c2 + a2 * exp( b2 * X_MAX) == Y_MAX
    
    # a1 * exp(-b1 * X_MIN) == c1 - Y_MIN
    # a1 * exp(-b1 * X_CTR) == c1 - Y_CTR
    # a2 * exp( b2 * X_CTR) == Y_CTR - c2
    # a2 * exp( b2 * X_MAX) == Y_MAX - c2
    
    # log(a1) - b1 * X_MIN == log(c1 - Y_MIN)
    # log(a1) - b1 * X_CTR == log(c1 - Y_CTR)
    # log(a2) + b2 * X_CTR == log(Y_CTR - c2)
    # log(a2) + b2 * X_MAX == log(Y_MAX - c2)
    
    # b1 * (X_CTR - X_MIN) == log(c1 - Y_MIN) - log(c1 - Y_CTR)
    # b2 * (X_MAX - X_CTR) == log(Y_MAX - c2) - log(Y_CTR - c2)
    
    b1 = (log(c1 - Y_MIN) - log(c1 - Y_CTR)) / (X_CTR - X_MIN)
    b2 = (log(Y_MAX - c2) - log(Y_CTR - c2)) / (X_MAX - X_CTR)
    
    # log(a1) == log(c1 - Y_MIN) + b1 * X_MIN
    # log(a2) == log(Y_MAX - c2) - b2 * X_MAX
    
    a1 = exp(log(c1 - Y_MIN) + b1 * X_MIN)
    a2 = exp(log(Y_MAX - c2) - b2 * X_MAX)
    
    x_lst = list(range(X_MIN, X_MAX+1))
    y_lst = [c1 - a1 * exp(-b1 * x) if x < X_CTR else
             c2 + a2 * exp( b2 * x) for x in x_lst]
    
    if plot:
        plt.plot(x_lst, y_lst)
        plt.grid(True)
        plt.show()
    else:
        for x, y in zip(x_lst, y_lst):
            print(f"{x},{y:.14}")
    
    

    E.g., with this input:

    c1 (> 2.1): 2.13
    c2 (< 2.1): 2.08
    plot? (y|n): y
    

    the output is: plot