2D линейная интерполяция: данные и интерполированные точки

Рассмотрим эту функцию y(x):

введите здесь описание изображения

где мы можем сгенерировать эти разбросанные точки в файле: dataset_1D.dat:

# x   y   
0   0
1   1
2   0
3   -9
4   -32

Ниже приведен код интерполяции 1D для этих точек:

  1. Загрузите эти разбросанные точки

  2. Создайте x_mesh

  3. Выполнение одномерной интерполяции

Код:

import numpy as np
from scipy.interpolate import interp2d, interp1d, interpnd
import matplotlib.pyplot as plt


# Load the data:    
x, y  = np.loadtxt('./dataset_1D.dat', skiprows = 1).T

# Create the function Y_inter for interpolation:
Y_inter = interp1d(x,y)

# Create the x_mesh:    
x_mesh = np.linspace(0, 4, num=10)
print x_mesh

# We calculate the y-interpolated of this x_mesh :   
Y_interpolated = Y_inter(x_mesh)
print Y_interpolated

# plot:

plt.plot(x_mesh, Y_interpolated, "k+")
plt.plot(x, y, 'ro')
plt.legend(['Linear 1D interpolation', 'data'], loc='lower left',  prop={'size':12})
plt.xlim(-0.1, 4.2)
plt.grid()
plt.ylabel('y')
plt.xlabel('x')
plt.show()

Это строит следующее:

введите здесь описание изображения

Теперь рассмотрим эту функцию z(x,y):

введите здесь описание изображения

где мы можем сгенерировать эти разбросанные точки в файле: dataset_2D.dat :

# x    y    z
0   0   0
1   1   0
2   2   -4
3   3   -18
4   4   -48

В этом случае нам пришлось бы выполнить 2D-интерполяцию:

import numpy as np
from scipy.interpolate import interp1d, interp2d, interpnd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Load the data:
x, y, z  = np.loadtxt('./dataset_2D.dat', skiprows = 1).T

# Create the function Z_inter for interpolation:
Z_inter = interp2d(x, y, z)

# Create the x_mesh and y_mesh :
x_mesh = np.linspace(1.0, 4, num=10)
y_mesh = np.linspace(1.0, 4, num=10)
print x_mesh
print y_mesh

# We calculate the z-interpolated of this x_mesh and y_mesh :
Z_interpolated = Z_inter(x_mesh, y_mesh)
print Z_interpolated
print type(Z_interpolated)
print Z_interpolated.shape

# plot: 
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x, y, z, c='r', marker='o')
plt.legend(['data'], loc='lower left',  prop={'size':12})
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

plt.show()

Это строит следующее:

введите здесь описание изображения

где разбросанные данные снова показаны красными точками, чтобы соответствовать 2D-графику.

  1. Я не знаю, как интерпретировать результат Z_interpolated:

    Согласно строкам печати для приведенного выше кода, Z_interpolated представляет собой n-мерный массив numpy формы (10,10). Другими словами, двумерная матрица с 10 строками и 10 столбцами.

Я ожидал интерполированное значение z[i] для каждого значения x_mesh[i] и y_mesh[i] Почему я не получаю это?

  1. Как я мог также отображать интерполированные данные в 3D-графике (точно так же, как черные кресты на 2D-графике)?

person DavidC.    schedule 05.07.2017    source источник


Ответы (2)


Интерпретация Z_interpolated: ваши одномерные x_mesh и y_mesh определяют сетка для интерполяции. Таким образом, результат вашей двухмерной интерполяции z представляет собой двумерный массив с формой (len(y), len(x)), которая соответствует np.meshgrid(x_mesh, y_mesh). Как видите, ваше z[i, i] вместо z[i] является ожидаемым значением для x_mesh[i] и y_mesh[i]. И у него намного больше, все значения на сетке.

Потенциальный график для отображения всех интерполированных данных:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import interp2d

# Your original function
x = y = np.arange(0, 5, 0.1)
xx, yy = np.meshgrid(x, y)
zz = 2 * (xx ** 2) - (xx ** 3) - (yy ** 2)

# Your scattered points
x = y = np.arange(0, 5)
z = [0, 0, -4, -18, -48]

# Your interpolation
Z_inter = interp2d(x, y, z)
x_mesh = y_mesh = np.linspace(1.0, 4, num=10)
Z_interpolated = Z_inter(x_mesh, y_mesh)

fig = plt.figure()
ax = fig.gca(projection='3d')
# Plot your original function
ax.plot_surface(xx, yy, zz, color='b', alpha=0.5)
# Plot your initial scattered points
ax.scatter(x, y, z, color='r', marker='o')
# Plot your interpolation data
X_real_mesh, Y_real_mesh = np.meshgrid(x_mesh, y_mesh)
ax.scatter(X_real_mesh, Y_real_mesh, Z_interpolated, color='g', marker='^')
plt.show()

введите здесь описание изображения

person Y. Luo    schedule 05.07.2017
comment
Большое спасибо за ваш ответ. В своем посте я использовал interp2d, чтобы использовать лучшую кубическую интерполяцию. Реализуя это в своем коде, он Z_inter = interp2d(x, y, z, kind='cubic') не работает, знаете почему? Спасибо - person DavidC.; 12.07.2017

Вам потребуется два шага интерполяции. Первый выполняет интерполяцию между данными y. А второй выполняет интерполяцию между данными z. Затем вы строите x_mesh с двумя интерполированными массивами.

x_mesh = np.linspace(0, 4, num=16)

yinterp = np.interp(x_mesh, x, y)
zinterp = np.interp(x_mesh, x, z)

ax.scatter(x_mesh, yinterp, zinterp, c='k', marker='s')

В приведенном ниже полном примере я также добавил некоторые изменения в направлении Y, чтобы сделать решение более общим.

u = u"""# x    y    z
0   0   0
1   3   0
2   9   -4
3   16   -18
4   32   -48"""

import io
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Load the data:
x, y, z  = np.loadtxt(io.StringIO(u), skiprows = 1, unpack=True)

x_mesh = np.linspace(0, 4, num=16)

yinterp = np.interp(x_mesh, x, y)
zinterp = np.interp(x_mesh, x, z)

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x_mesh, yinterp, zinterp, c='k', marker='s')
ax.scatter(x, y, z, c='r', marker='o')
plt.legend(['data'], loc='lower left',  prop={'size':12})
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

plt.show()

введите здесь описание изображения

Для использования scipy.interpolate.interp1d решение практически такое же:

u = u"""# x    y    z
0   0   0
1   3   0
2   9   -4
3   16   -18
4   32   -48"""

import io
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Load the data:
x, y, z  = np.loadtxt(io.StringIO(u), skiprows = 1, unpack=True)

x_mesh = np.linspace(0, 4, num=16)

fy = interp1d(x, y, kind='cubic')
fz = interp1d(x, z, kind='cubic')

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x_mesh, fy(x_mesh), fz(x_mesh), c='k', marker='s')
ax.scatter(x, y, z, c='r', marker='o')
plt.legend(['data'], loc='lower left',  prop={'size':12})
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

plt.show()
person ImportanceOfBeingErnest    schedule 05.07.2017
comment
Большое спасибо за ваш ответ. К сожалению, np.interp допускает только линейную интерполяцию. Вот почему я использовал interp1d scipy, чтобы лучше соответствовать z(x,y), который является кубическим в x. Следуя вашим указаниям и переводя это в interp1d, мы бы: 1) Интерполировали между данными y: Y_inter = interp1d(x,y, kind='cubic') и 2) Интерполировали между данными z: Z_inter = interp1d(x,z, kind='cubic'). Тогда мы могли бы сделать Z_interpolated = Z_inter(x_mesh, y_mesh) (мой пост), но это не дает правильного ответа... Как мы могли этого добиться? Спасибо - person DavidC.; 11.07.2017
comment
Спасибо, я копаю в этом - person DavidC.; 12.07.2017