Построение 2-го интерполятора с учетом разбросанных входных данных - PullRequest
0 голосов
/ 29 октября 2018

У меня есть три списка следующим образом:

x = [100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0]

y = [300.0, 300.0, 300.0, 300.0, 500.0, 500.0, 500.0, 500.0, 700.0, 700.0, 700.0, 700.0, 1000.0, 1000.0, 1000.0, 1000.0, 1500.0, 1500.0, 1500.0, 1500.0, 2000.0, 2000.0, 2000.0, 2000.0, 3000.0, 3000.0, 3000.0, 3000.0, 5000.0, 5000.0, 5000.0, 5000.0, 7500.0, 7500.0, 7500.0, 75000.0, 10000.0, 10000.0, 10000.0, 10000.0]

z = [100.0, 95.0, 87.5, 77.5, 60.0, 57.0, 52.5, 46.5, 40.0, 38.0, 35.0, 31.0, 30.0, 28.5, 26.25, 23.25, 23.0, 21.85, 20.125, 17.825, 17.0, 16.15, 14.875, 13.175, 13.0, 12.35, 11.375, 10.075, 10.0, 9.5, 8.75, 7.75, 7.0, 6.65, 6.125, 5.425, 5.0, 4.75, 4.375, 3.875]

Каждая запись каждого списка читается как точка, поэтому точка 0 равна (100 300 100), точка 1 равна (75 300 95) и т. Д.

Я пытаюсь выполнить 2-мерную интерполяцию, чтобы я мог вычислить значение z для любого заданного входного значения (x0, y0).

Я читал, что используя сетку я могу интерполировать с RegularGridInterpolator из Scipy, но я не уверен, как настроить его, когда я делаю:

x_,y_,z_ = np.meshgrid(x,y,z) # both indexing ij or xy

Я не получаю значения для x_,y_,z_, которые имеют смысл, и я не уверен, как оттуда идти.

Я пытаюсь использовать точки данных, которые у меня есть выше, чтобы найти промежуточные значения, так что-то похожее на interp1d scipy, где

f = interp1d(x, y, kind='cubic')

, где я могу позже позвонить f(any (x,y) point within range) и получить соответствующее значение z.

1 Ответ

0 голосов
/ 29 октября 2018

Вам необходима 2-мерная интерполяция по разбросанным данным.В этом случае я бы по умолчанию использовал scipy.interpolate.griddata, но вам, похоже, нужен интерполятор , который можно вызвать , тогда как griddata нужен определенный набор точек, на которые он будет интерполироваться.

Не беспокойтесь: griddata с 2-мерной кубической интерполяцией использует CloughTocher2DInterpolator.Таким образом, мы можем сделать именно это:

import numpy as np
import scipy.interpolate as interp

x = [100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0, 100.0, 75.0, 50.0, 0.0]
y = [300.0, 300.0, 300.0, 300.0, 500.0, 500.0, 500.0, 500.0, 700.0, 700.0, 700.0, 700.0, 1000.0, 1000.0, 1000.0, 1000.0, 1500.0, 1500.0, 1500.0, 1500.0, 2000.0, 2000.0, 2000.0, 2000.0, 3000.0, 3000.0, 3000.0, 3000.0, 5000.0, 5000.0, 5000.0, 5000.0, 7500.0, 7500.0, 7500.0, 75000.0, 10000.0, 10000.0, 10000.0, 10000.0]
z = [100.0, 95.0, 87.5, 77.5, 60.0, 57.0, 52.5, 46.5, 40.0, 38.0, 35.0, 31.0, 30.0, 28.5, 26.25, 23.25, 23.0, 21.85, 20.125, 17.825, 17.0, 16.15, 14.875, 13.175, 13.0, 12.35, 11.375, 10.075, 10.0, 9.5, 8.75, 7.75, 7.0, 6.65, 6.125, 5.425, 5.0, 4.75, 4.375, 3.875]

interpolator = interp.CloughTocher2DInterpolator(np.array([x,y]).T, z)

Теперь вы можете вызвать этот интерполятор с двумя координатами, чтобы получить соответствующую интерполированную точку данных:

>>> interpolator(x[10], y[10]) == z[10]
True
>>> interpolator(2, 300)
array(77.81343)

Обратите внимание, что вам придетсяоставайтесь внутри выпуклой оболочки входных точек, в противном случае вы получите nan (или все, что передано в качестве ключевого слова fill_value интерполятору):

>>> interpolator(2, 30)
array(nan)

В любом случае экстраполяция обычно не имеет смысла, иВаши входные точки разбросаны немного хаотично:

location of base points for interpolation

Так что даже если бы экстраполяция была возможной, я бы не поверил.


Для демонстрации того, как полученный интерполятор ограничен выпуклой оболочкой входных точек, приведен поверхностный график ваших данных на сетке с сеткой, которую мы создаем только для построения графика:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# go linearly in the x grid
xline = np.linspace(min(x), max(x), 30)
# go logarithmically in the y grid (considering y distribution)
yline = np.logspace(np.log10(min(y)), np.log10(max(y)), 30)
# construct 2d grid from these
xgrid,ygrid = np.meshgrid(xline, yline)
# interpolate z data; same shape as xgrid and ygrid
z_interp = interpolator(xgrid, ygrid)

# create 3d Axes and plot surface and base points
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(xgrid, ygrid, z_interp, cmap='viridis',
                vmin=min(z), vmax=max(z))
ax.plot(x, y, z, 'ro')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

plt.show()

Вотвывод с двух сторон (лучше вращаться в интерактивном режиме; такие кадры не отражают 3D-представление):

first shot of surface plot second shot of surface plot

Есть тОбратите внимание на две основные особенности:

  1. Поверхность хорошо вписывается в красные точки, что ожидается от интерполяции.К счастью, точки ввода хороши и гладки, поэтому все идет хорошо с интерполяцией.(Тот факт, что красные точки обычно скрыты поверхностью, объясняется только тем, как средство визуализации pyplot неправильно обрабатывает относительное положение сложных трехмерных объектов)
  2. Поверхность обрезается (из-за значений nan) вдоль выпуклойкорпус входных точек, поэтому даже если наши сеточные массивы определяют прямоугольную сетку, мы получаем только участок поверхности, где имеет смысл интерполяция.
...