I have 3 arrays: a, b, c all with length 15.
a=[950, 850, 750, 675, 600, 525, 460, 400, 350, 300, 250, 225, 200, 175, 150] b = [16, 12, 9, -35, -40, -40, -40, -45, -50, -55, -60, -65, -70, -75, -80]c=[32.0, 22.2, 12.399999999999999, 2.599999999999998, -7.200000000000003, -17.0, -26.800000000000004, -36.60000000000001, -46.400000000000006, -56.2, -66.0, -75.80000000000001, -85.60000000000001, -95.4, -105.20000000000002]I am trying to find the value of a at the index where b=c. T
The problem is that there is no place where b=c exactly so I need to linearly interpolate between values in the array to find the value of a where b=c. Does that make sense?
I was thinking about usingscipy.interpolate to do the interpolation.
I am having a hard time wrappying my mind around how to solve this problem. Any ideas on this would be great!
- Can you add some examples of arrays
a,b, andc?Christian Ternus– Christian Ternus2016-09-12 19:31:55 +00:00CommentedSep 12, 2016 at 19:31 b = [16, 12, 9, -35, -40, -40, -40, -45, -50, -55, -60, -65, -70, -75, -80])c=[32.0, 22.2, 12.399999999999999, 2.599999999999998, -7.200000000000003, -17.0, -26.800000000000004, -36.60000000000001, -46.400000000000006, -56.2, -66.0, -75.80000000000001, -85.60000000000001, -95.4, -105.20000000000002]a=[950, 850, 750, 675, 600, 525, 460, 400, 350, 300, 250, 225, 200, 175, 150]HM14– HM142016-09-12 19:34:23 +00:00CommentedSep 12, 2016 at 19:34- Define
interpolate linearily(what do you mean? linear-regression on all points; piecewise-linear? is it a valid assumption in regards to the data?...). Also: instead of adding this example as comment, edit your question and format it nicely!sascha– sascha2016-09-12 21:07:08 +00:00CommentedSep 12, 2016 at 21:07 - Linear interpolation:en.wikipedia.org/wiki/Linear_interpolation. In particular, see "Linear interpolation of a data set":en.wikipedia.org/wiki/…Warren Weckesser– Warren Weckesser2016-09-12 21:50:39 +00:00CommentedSep 12, 2016 at 21:50
3 Answers3
Here's simpler variation of a function fromanother answer of mine:
from __future__ import divisionimport numpy as npdef find_roots(t, y): """ Given the input signal `y` with samples at times `t`, find the times where `y` is 0. `t` and `y` must be 1-D numpy arrays. Linear interpolation is used to estimate the time `t` between samples at which sign changes in `y` occur. """ # Find where y crosses 0. transition_indices = np.where(np.sign(y[1:]) != np.sign(y[:-1]))[0] # Linearly interpolate the time values where the transition occurs. t0 = t[transition_indices] t1 = t[transition_indices + 1] y0 = y[transition_indices] y1 = y[transition_indices + 1] slope = (y1 - y0) / (t1 - t0) transition_times = t0 - y0/slope return transition_timesThat function can be used witht = a andy = b - c. For example, here is your data, entered as numpy arrays:
In [354]: a = np.array([950, 850, 750, 675, 600, 525, 460, 400, 350, 300, 250, 225, 200, 175, 150])In [355]: b = np.array([16, 12, 9, -35, -40, -40, -40, -45, -50, -55, -60, -65, -70, -75, -80])In [356]: c = np.array([32.0, 22.2, 12.399999999999999, 2.599999999999998, -7.200000000000003, -17.0, -26.800000000000004, -3 ...: 6.60000000000001, -46.400000000000006, -56.2, -66.0, -75.80000000000001, -85.60000000000001, -95.4, -105.2000000000 ...: 0002])The place where "b = c" is the place where "b - c = 0", so we passb - c fory:
In [357]: find_roots(a, b - c)Out[357]: array([ 312.5])So the linearly interpolated value ofa is 312.5.
With the following matplotlib commands:
In [391]: plot(a, b, label="b")Out[391]: [<matplotlib.lines.Line2D at 0x11eac8780>]In [392]: plot(a, c, label="c")Out[392]: [<matplotlib.lines.Line2D at 0x11f23aef0>]In [393]: roots = find_roots(a, b - c)In [394]: [axvline(root, color='k', alpha=0.2) for root in roots]Out[394]: [<matplotlib.lines.Line2D at 0x11f258208>]In [395]: grid()In [396]: legend(loc="best")Out[396]: <matplotlib.legend.Legend at 0x11f260ba8>In [397]: xlabel("a")Out[397]: <matplotlib.text.Text at 0x11e71c470>I get the plot
Comments
This is not necessarily a solution to your problem, since your data does not appear to be linear, but it might give you some ideas. If you assume that your lines a, b, and c are linear, then the following idea works:
Perform a linear regression of lines a, b and c to get their respective slopes (m_a, m_b, m_c) and y-intercepts (b_a, b_b, b_c). Then solve the equation 'y_b = y_c' for x, and find y = m_a * x + b_a to get your result.
Since the linear regression approximately solves y = m * x + b, equation y_b = y_c can be solved by hand giving: x = (b_b-b_c) / (m_c-m_b).
Using python, you get:
>> m_a, b_a, r_a, p_a, err_a = stats.linregress(range(15), a)>> m_b, b_b, r_b, p_b, err_b = stats.linregress(range(15), b)>> m_c, b_c, r_c, p_c, err_c = stats.linregress(range(15), c)>> x = (b_b-b_c) / (m_c-m_b)>> m_a * x + b_a379.55151515151516Since your data is not linear, you probably need to go through your vectors one by one and search for overlapping y intervals. Then you can apply the above method but using only the endpoints of your two intervals to construct your b and c inputs to the linear regression. In this case, you should get an exact result, since the least-squares method will interpolate perfectly with only two points (although there are more efficient ways to do this since the intersection can be solved exactly in this simple case where there are two straight lines).
Cheers.
1 Comment
Another simple solution using:
- one linear-regressor for each vector (done with scikit-learn as scipy-docs were down for me; easy to switch to numpy/scipy-based linear-regression)
- general-purpose minimization usingscipy.optimize.minimize
Code
a=[950, 850, 750, 675, 600, 525, 460, 400, 350, 300, 250, 225, 200, 175, 150]b = [16, 12, 9, -35, -40, -40, -40, -45, -50, -55, -60, -65, -70, -75, -80]c=[32.0, 22.2, 12.399999999999999, 2.599999999999998, -7.200000000000003, -17.0, -26.800000000000004, -36.60000000000001, -46.400000000000006, -56.2, -66.0, -75.80000000000001, -85.60000000000001, -95.4, -105.20000000000002]from sklearn.linear_model import LinearRegressionfrom scipy.optimize import minimizeimport numpy as npreg_a = LinearRegression().fit(np.arange(len(a)).reshape(-1,1), a)reg_b = LinearRegression().fit(np.arange(len(b)).reshape(-1,1), b)reg_c = LinearRegression().fit(np.arange(len(c)).reshape(-1,1), c)funA = lambda x: reg_a.predict(x.reshape(-1,1))funB = lambda x: reg_b.predict(x.reshape(-1,1))funC = lambda x: reg_c.predict(x.reshape(-1,1))opt_crossing = lambda x: (funB(x) - funC(x))**2x0 = 1res = minimize(opt_crossing, x0, method='SLSQP', tol=1e-6)print(res)print('Solution: ', funA(res.x))import matplotlib.pyplot as pltx = np.linspace(0, 15, 100)a_ = reg_a.predict(x.reshape(-1,1))b_ = reg_b.predict(x.reshape(-1,1))c_ = reg_c.predict(x.reshape(-1,1))plt.plot(x, a_, color='blue')plt.plot(x, b_, color='green')plt.plot(x, c_, color='cyan')plt.scatter(np.arange(15), a, color='blue')plt.scatter(np.arange(15), b, color='green')plt.scatter(np.arange(15), c, color='cyan')plt.axvline(res.x, color='red', linestyle='solid')plt.axhline(funA(res.x), color='red', linestyle='solid')plt.show()Output
fun: array([ 7.17320622e-15])jac: array([ -3.99479864e-07, 0.00000000e+00])message: 'Optimization terminated successfully.'nfev: 8nit: 2njev: 2status: 0success: True x: array([ 8.37754008])Solution: [ 379.55151658]Plot
2 Comments
Explore related questions
See similar questions with these tags.

