2 votes

Essayer d'interpoler linéairement en python

J'ai 3 tableaux : a, b, c, tous de longueur 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] 

Je cherche à trouver la valeur de a à l'indice où b=c. T

Le problème est qu'il n'y a aucun endroit où b=c exactement. Je dois donc interpoler linéairement entre les valeurs du tableau pour trouver la valeur de a où b=c. Est-ce que cela a un sens ?

Je pensais utiliser scipy.interpolate pour effectuer l'interpolation.

J'ai du mal à me faire une idée de la manière de résoudre ce problème. Toute idée à ce sujet serait la bienvenue !

3voto

Warren Weckesser Points 17089

Voici une variation plus simple d'une fonction de une autre de mes réponses :

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

Cette fonction peut être utilisée avec t = a y y = b - c . Par exemple, voici vos données, saisies sous forme de tableaux 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])

L'endroit où "b = c" est l'endroit où "b - c = 0", donc on passe b - c pour y :

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

Ainsi, la valeur interpolée linéairement de a est de 312,5.

Avec les commandes matplotlib suivantes :

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>

J'obtiens l'intrigue

plot

0voto

sascha Points 17084

Une autre solution simple utilisant :

  • un régresseur linéaire pour chaque vecteur (fait avec scikit-learn car scipy-docs n'était pas disponible pour moi ; facile de passer à la régression linéaire basée sur numpy/scipy)
  • minimisation à usage général utilisant 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()

Sortie

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

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X