Многомерная интерполяция? - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть такие данные.Скорость по оси x и мощность по оси y.Это дает один сюжет.Но есть ряд, скажем, значений C, которые дают другие графики также на диаграмме скорость-мощность.

Данные:

C = 12
speed:[127.1, 132.3, 154.3, 171.1, 190.7, 195.3]
power:[2800, 3400.23, 5000.1, 6880.7, 9711.1, 10011.2 ]

C = 14
speed:[113.1, 125.3, 133.3, 155.1, 187.7, 197.3]
power:[2420, 3320, 4129.91, 6287.17, 10800.34, 13076.5 ]

Теперь я хочу иметь возможностьнапример, интерполировать на [[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]].

Я прочитал этот ответ.Я не уверен, если это способ сделать это.

Я пытался:

data = np.array([[12, 127.1, 2800], [12, 132.3, 3400.23], [12, 154.3, 5000.1], [12, 171.1, 6880.7],
                [12, 190.7, 9711.1], [12, 195.3, 10011.2],
                [14, 113.1, 2420], [14, 125.3, 3320], [14, 133.3, 4129.91], [14, 155.1, 6287.17],
                [14, 187.7, 10800.34], [14, 197.3, 13076.5]])

coords = np.array([[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]])

z = ndimage.map_coordinates(data, coords.T, order=2, mode='nearest')

, но я получаю:

array([13076.5, 13076.5, 13076.5, 13076.5, 13076.5, 13076.5])

Я не уверенкак бороться с такого рода интерполяцией.

Ответы [ 3 ]

0 голосов
/ 21 ноября 2018

Предполагая, что ваша функция имеет вид power = F (C, скорость), вы можете использовать scipy.interpolate.interp2d:

import scipy.interpolate as sci

speed = [127.1, 132.3, 154.3, 171.1, 190.7, 195.3]
C = [12]*len(speed)
power = [2800, 3400.23, 5000.1, 6880.7, 9711.1, 10011.2 ]

speed += [113.1, 125.3, 133.3, 155.1, 187.7, 197.3]
C += [14]*(len(speed) - len(C))
power += [2420, 3320, 4129.91, 6287.17, 10800.34, 13076.5 ]

f = sci.interp2d(C, speed, power)

coords = np.array([[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]])
power_interp = np.concatenate([f(*coord) for coord in coords])

with np.printoptions(precision=1, suppress=True, linewidth=9999):
    print(power_interp)

Это выводит:

[1632.4 2659.5 3293.4 4060.2 5074.8 4506.6]

, который кажется немного низким.Причина этого заключается в том, что interp2d по умолчанию использует линейный сплайн, и ваши данные определенно нелинейны.Вы можете получить лучшие результаты, непосредственно обращаясь к процедурам подгонки сплайна через LSQBivariateSpline:

xknots = (min(C), max(C))
yknots = (min(speed), max(speed))
f = sci.LSQBivariateSpline(C, speed, power, tx=xknots, ty=yknots, kx=2, ky=3)

power_interp = f(*coords.T, grid=False)

with np.printoptions(precision=1, suppress=True, linewidth=9999):
    print(power_interp)

Это приводит к:

[ 2753.2  3780.8  5464.5  7505.2 10705.9 11819.6]

, что кажется более разумным.

0 голосов
/ 22 ноября 2018

map_coordinates предполагает, что у вас есть элементы с каждым целочисленным индексом, как на изображении.Т.е. (0, 0), (0, 1) ..., (0, 100), (1, 0), (1, 1), ..., (100, 0), (100, 1),..., (100, 100) - все координаты, которые хорошо определены, если у вас есть изображение 100x100.Это не твой случай.У вас есть данные в координатах (12, 127.1), (12, 132.3) и т. Д.

Вместо них можно использовать griddata.В зависимости от того, как вы хотите интерполировать, вы получите разные результаты:

In [24]: data = np.array([[12, 127.1, 2800], [12, 132.3, 3400.23], [12, 154.3, 5000.1], [12, 171.1, 6880.7],
    ...:                 [12, 190.7, 9711.1], [12, 195.3, 10011.2],
    ...:                 [14, 113.1, 2420], [14, 125.3, 3320], [14, 133.3, 4129.91], [14, 155.1, 6287.17],
    ...:                 [14, 187.7, 10800.34], [14, 197.3, 13076.5]])

In [25]: from scipy.interpolate import griddata

In [28]: coords = np.array([[12.2, 122.1], [12.4, 137.3], [12.5, 154.9], [12.6, 171.4], [12.7, 192.6], [12.8, 198.5]])

In [29]: griddata(data[:, 0:2], data[:, -1], coords)
Out[29]:
array([           nan,  3895.22854545,  5366.64369048,  7408.68906748,
       10791.779     ,            nan])

In [31]: griddata(data[:, 0:2], data[:, -1], coords, method='nearest')
Out[31]: array([ 3320.  ,  4129.91,  5000.1 ,  6880.7 ,  9711.1 , 13076.5 ])

In [32]: griddata(data[:, 0:2], data[:, -1], coords, method='cubic')
Out[32]:
array([           nan,  3998.75479082,  5357.54672326,  7297.94115979,
       10647.04183455,            nan])

method='cubic', вероятно, имеет самую высокую точность для "случайных" данных, но только вы можете решить, какой метод подходит для ваших данныхи что вы пытаетесь сделать (по умолчанию method='linear', используется в [29] выше).

Обратите внимание, что некоторые из ответов nan.Это потому, что вы дали ввод, который находится не внутри «ограничивающего многоугольника», который ваши точки образуют в 2D-пространстве.

Вот визуализация, чтобы показать вам, что я имею в виду:

In [49]: x = plt.scatter(x=np.append(data[:, 0], [12.2, 12.8]), y=np.append(data[:, 1], [122.1, 198.5]), c=['green']*len(data[:, 0]) + ['red']*2)

In [50]: plt.show()

bounding polygon

Я не соединял точки зеленого цвета, но вы можете видеть, что две точки красного цвета находятся за пределами многоугольника, который был бы сформирован, если бы я соединил эти точки.точек.Вы не можете интерполировать за пределами этого диапазона, поэтому вы получите nan.Чтобы понять почему, рассмотрим 1D случай.Если я спрошу вас, какое значение имеет индекс 2.5 [0,1,2,3], разумный ответ будет 2.5.Однако, если я спрашиваю, что находится на значении индекса 100 ... априори мы не имеем представления, что на уровне 100, это слишком далеко за пределами диапазона того, что вы можете видеть.Поэтому мы не можем дать ответ.Сказать, что это 100, неправильно для этой функции, поскольку это будет экстраполяция , а не интерполяция .

HTH.

0 голосов
/ 21 ноября 2018

Мне кажется, что все, что у вас здесь есть:

скорость = F (C) и мощность = G (C)

Так что вам не нужна многомерная интерполяция, просто interp1d для создания одной функции для скорости, а другой для мощности ...

...