pythonanalysisintercept

Finding the corresponding X-axis value from graph


Please check my code from the internet. I am trying to find the X-axis values at 10, 50 and 90 Y-axis values from the chart. But np.intercep() is not working.

I have tried the Y-Intercept and other methods. But couldn't find a solution of my problem.

from pandas import DataFrame
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data = {'opening': [4.75, 2, 0.850, 0.425, 0.250, 0.150, 0.075],
        'mass_retained': [0, 10.7, 14.3, 20.8, 23.8, 15.7, 9.2]}

df = DataFrame(data)

def calculate_percent_finer(df):
    total_mass = df.mass_retained.sum()
    arr = []
    for count, sieve in enumerate(df.opening.values):
        cumulative_mass = sum([df.mass_retained.values[i] for i in range(count + 1)])
        percent_finer = ((total_mass - cumulative_mass) / total_mass) * 100
        arr.append(percent_finer)
    return df.assign(p_finer=arr)

df2 = calculate_percent_finer(df)

x= df2.opening
y= df2.p_finer
plt.style.use('bmh')
plt.plot(df2.opening, df2.p_finer,'-gD')
plt.gca().invert_xaxis()
plt.xlabel('Grain Size (mm)')
plt.ylabel('Percent Passing')

plt.show()


I have used the following code. but it didnt work

np.interp(10, df2.p_finer,df2.opening)

And is there a way I can draw those lines y=10, 50 and 90 on the graph as well to see the X-axis values.


Solution

  • To have np.interp work correctly, every element must be greater than the previous in the axis, which is not the case in the original data, so we can add df2.sort_values('p_finer', inplace=True) to make it true, in which case that call works as expected.

    In order to put some lines on the graph to show where these interpolations are we can loop over the requested values and add some lines using the same plotting call you already used.

    Here is an example of those with minimal alterations to your original code:

    from pandas import DataFrame
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    
    requested_values = [10, 50, 90]
    
    data = {'opening': [4.75, 2, 0.850, 0.425, 0.250, 0.150, 0.075],
            'mass_retained': [0, 10.7, 14.3, 20.8, 23.8, 15.7, 9.2]}
    
    df = DataFrame(data)
    
    def calculate_percent_finer(df):
        total_mass = df.mass_retained.sum()
        arr = []
        for count, sieve in enumerate(df.opening.values):
            cumulative_mass = sum([df.mass_retained.values[i] for i in range(count + 1)])
            percent_finer = ((total_mass - cumulative_mass) / total_mass) * 100
            arr.append(percent_finer)
        return df.assign(p_finer=arr)
    
    df2 = calculate_percent_finer(df)
    df2.sort_values('p_finer', inplace=True)
    
    x= df2.opening
    y= df2.p_finer
    plt.style.use('bmh')
    plt.plot(df2.opening, df2.p_finer,'-gD')
    plt.gca().invert_xaxis()
    plt.xlabel('Grain Size (mm)')
    plt.ylabel('Percent Passing')
    
    for interp_value in requested_values:
        calced_interp = np.interp(interp_value, df2.p_finer, df2.opening)
        print(interp_value, calced_interp)
        plt.plot([calced_interp, max(df2.opening)], [interp_value] * 2, '-', linewidth=1, color='grey', label=f'{interp_value:3} -> {calced_interp:5.3f}')
        plt.plot([calced_interp] * 2, [interp_value, min(df2.opening)], '-', linewidth=1, color='grey')
    plt.legend()
    plt.show()
    

    When I run that I get the following console print and plot:

    10 0.15159235668789806
    50 0.4143382352941176
    90 2.321261682242992
    

    demonstration matplotlib plot with grey lines shown at requested interpolation values

    Let me know if you have any questions!