#python #scipy #interpolation
#python #scipy #интерполяция
Вопрос:
Учитывая некоторые данные
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
x = [0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,]
y = [0.01,0.01,0.01,0.255,0.255,0.255,0.5,0.5,0.5,0.01,0.01,0.01,0.255,0.255,0.255,0.5,0.5,0.5,0.01,0.01,0.01,0.255,0.255,0.255,0.5,0.5,0.5,]
z = [0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2]
v = [0.,0.,1.,0.,1.,1.,0.,1.,1.,0.,0.,0.,0.,0.5,1.,0.,1.,1.,0.,0.,0.,0.,0.,0.,0.,0.5,1.,]
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
c = ax.scatter(x, y, z, c = v, s = 100, cmap = plt.cm.bwr, edgecolor = "black", alpha = 0.2)
ax.scatter(0.51, 0.32, 0.12, s = 100, c = "black", edgecolor = "black")
plt.show()
Я хочу получить функцию f(x,y,z)
, чтобы выяснить, каким должно быть значение v
в любой произвольной позиции. Просто, не так ли? Тогда почему я не могу из любви к scipy разобраться, как это сделать?
Найденные мной примеры определяют x, y, z, определяют некоторого рода сетку и вычисляют, чтобы получить v
правильную форму и порядок. На этом мои попытки заканчиваются неудачей. Что, если все данные изначально отформатированы как 1D?
Я думал, что смогу сделать
V = zeros((len(x),len(y),len(z)))
for i in range(len(x)):
V[i, None, None] = v[i]
for j in range(len(y)):
V[None, j, None] = v[j]
for k in range(len(z)):
V[None, None, k] = v[k]
fn = RegularGridInterpolator((x,y,z), V)
Но это возвращает ValueError: The points in dimension 0 must be strictly ascending
Ответ №1:
Вы хотите использовать griddata, вот пример использования ваших данных,
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from scipy.interpolate import griddata
import numpy as np
x = [0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.46,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,0.9,]
y = [0.01,0.01,0.01,0.255,0.255,0.255,0.5,0.5,0.5,0.01,0.01,0.01,0.255,0.255,0.255,0.5,0.5,0.5,0.01,0.01,0.01,0.255,0.255,0.255,0.5,0.5,0.5,]
z = [0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2,0.,0.1,0.2]
v = [0.,0.,1.,0.,1.,1.,0.,1.,1.,0.,0.,0.,0.,0.5,1.,0.,1.,1.,0.,0.,0.,0.,0.,0.,0.,0.5,1.,]
points = np.array([x, y, z])
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
c = ax.scatter(x, y, z, c=v, s = 100, cmap = plt.cm.bwr, edgecolor = "black", alpha = 0.2)
# This is the interpolation, use existing points and values (1D)
# to get the value at 0.51, 0.32, 0.12
p = griddata(points.T, v, (0.51, 0.32, 0.12))
ax.scatter(0.51, 0.32, 0.12, s=100, c=[p], cmap = plt.cm.bwr)
#Plot a meshgrid of interpolated values (optional)
pad = 0.02
xg = np.linspace(min(x)-pad, max(x) pad,10)
yg = np.linspace(min(y)-pad, max(y) pad,10)
zg = np.linspace(min(z)-pad, max(z) pad,10)
X, Y, Z = np.meshgrid(xg, yg, zg)
vinterp = griddata(points.T, v, (X, Y, Z))
ci = ax.scatter(X.ravel(), Y.ravel(), Z.ravel(), c=vinterp.ravel(), s=10, cmap = plt.cm.bwr, edgecolor = "black", alpha = 0.2)
plt.show()
который выглядит следующим образом,
с помощью сетки значений, построенной для отображения интерполяции и вашей точки примера.
Комментарии:
1. Ах, это тот самый. Я также обернул его
__call__
, чтобы было немного удобнее носить с собой, как и другие функции Scipy:class Interpolate3D(): def __init__(self, x, y, z, v): self.x = x self.y = y self.z = z self.v = v self.pts = np.array([self.x, self.y, self.z]).T def __call__(self, *args): return scipy.interpolate.griddata(self.pts, self.v, args, method = "linear")