简体   繁体   English

试图在python中线性插值

[英]Trying to interpolate linearly in python

I have 3 arrays: a, b, c all with length 15. 我有3个数组:a,b,c的长度均为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. 我正在尝试在b = c的索引处找到a的值。 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. 问题在于,b = c完全没有位置,因此我需要在数组中的值之间线性插值以找到a的值,其中b = c。 Does that make sense? 那有意义吗?

I was thinking about using scipy.interpolate to do the interpolation. 我正在考虑使用scipy.interpolate进行插值。

I am having a hard time wrappying my mind around how to solve this problem. 我很难解决如何解决这个问题。 Any ideas on this would be great! 任何想法都很棒!

Here's simpler variation of a function from another answer of mine : 是我的另一个答案中函数的简单变化:

from __future__ import division

import numpy as np


def 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_times

That function can be used with t = a and y = b - c . 该函数可以与t = ay = b - c For example, here is your data, entered as numpy arrays: 例如,这是您的数据,以numpy数组形式输入:

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 pass b - c for y : “ b = c”的地方就是“ b-c = 0”的地方,因此我们将b - c传递给y

In [357]: find_roots(a, b - c)
Out[357]: array([ 312.5])

So the linearly interpolated value of a is 312.5. 因此, a的线性内插值为312.5。

With the following matplotlib commands: 使用以下matplotlib命令:

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 我知道了

情节

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: 如果假设您的线a,b和c是线性的,则以下想法可行:

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). 对线a,b和c进行线性回归以获得其各自的斜率(m_a,m_b,m_c)和y截距(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. 然后为x求解方程'y_b = y_c',找到y = m_a * x + b_a以得到结果。

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). 由于线性回归近似求解y = m * x + b,因此方程y_b = y_c可以手工给出:x =(b_b-b_c)/(m_c-m_b)来求解。

Using python, you get: 使用python,您将获得:

>> 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_a
379.55151515151516

Since your data is not linear, you probably need to go through your vectors one by one and search for overlapping y intervals. 由于数据不是线性的,因此您可能需要一个一个地遍历向量并搜索重叠的y间隔。 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. 然后,您可以应用上述方法,但仅使用两个间隔的端点来构造线性回归的b和c输入。 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. 干杯。

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) 每个向量一个线性回归器(对我来说,使用scikit-learn作为scipy-docs完成;很容易切换到基于numpy / scipy的线性回归)
  • general-purpose minimization using scipy.optimize.minimize 使用scipy.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 LinearRegression
from scipy.optimize import minimize
import numpy as np

reg_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))**2
x0 = 1
res = minimize(opt_crossing, x0, method='SLSQP', tol=1e-6)
print(res)
print('Solution: ', funA(res.x))

import matplotlib.pyplot as plt

x = 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: 8
nit: 2
njev: 2
status: 0
success: True
  x: array([ 8.37754008])
Solution:  [ 379.55151658]

Plot 情节

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM