Python 如果我想要随机非结构化数据的3D样条曲线/平滑插值,该怎么办?

Python 如果我想要随机非结构化数据的3D样条曲线/平滑插值,该怎么办?,python,scipy,interpolation,Python,Scipy,Interpolation,@James的灵感激发了我,让我了解如何使用griddata和map\u坐标。在下面的例子中,我展示了2D数据,但我的兴趣是3D。我注意到,griddata只提供1D和2D的样条曲线,并且仅限于3D和更高版本的线性插值(可能是出于非常好的原因)。然而,使用高阶(比分段线性插值更平滑)插值的3D地图坐标似乎很好 我的主要问题:如果我在3D中有随机的非结构化数据(我不能使用地图坐标),那么在NumPy SciPy宇宙中,或者至少在附近,是否有比分段线性插值更平滑的方法 我的第二个问题:spline

@James的灵感激发了我,让我了解如何使用
griddata
map\u坐标。在下面的例子中,我展示了2D数据,但我的兴趣是3D。我注意到,
griddata
只提供1D和2D的样条曲线,并且仅限于3D和更高版本的线性插值(可能是出于非常好的原因)。然而,使用高阶(比分段线性插值更平滑)插值的3D地图坐标似乎很好

我的主要问题:如果我在3D中有随机的非结构化数据(我不能使用地图坐标),那么在NumPy SciPy宇宙中,或者至少在附近,是否有比分段线性插值更平滑的方法

我的第二个问题:spline for 3D在
griddata
中不可用是因为它很难实现还是很繁琐,还是存在根本性的困难

下面的图片和可怕的python展示了我目前对griddata和map_坐标如何使用的理解。沿粗黑线进行插值

结构化数据:

import numpy as np
import matplotlib.pyplot as plt

def g(x, y):
    return np.exp(-((x-1.0)**2 + (y-1.0)**2))

def findit(x, X):  # or could use some 1D interpolation
    fraction = (x - X[0]) / (X[-1]-X[0])
    return fraction * float(X.shape[0]-1)

nth, nr = 12, 11
theta_min, theta_max = 0.2, 1.3
r_min,     r_max     = 0.7, 2.0

theta = np.linspace(theta_min, theta_max, nth)
r     = np.linspace(r_min,     r_max,     nr)

R, TH = np.meshgrid(r, theta)
Xp, Yp  = R*np.cos(TH), R*np.sin(TH)
array = g(Xp, Yp)

x, y = np.linspace(0.0, 2.0, 200), np.linspace(0.0, 2.0, 200)
X, Y = np.meshgrid(x, y)
blob = g(X, Y)

xtest = np.linspace(0.25, 1.75, 40)
ytest = np.zeros_like(xtest) + 0.75

rtest = np.sqrt(xtest**2 + ytest**2)
thetatest = np.arctan2(xtest, ytest)

ir = findit(rtest, r)
it = findit(thetatest, theta)

plt.figure()

plt.subplot(2,1,1)

plt.scatter(100.0*Xp.flatten(), 100.0*Yp.flatten())
plt.plot(100.0*xtest, 100.0*ytest, '-k', linewidth=3)
plt.hold
plt.imshow(blob, origin='lower', cmap='gray')

plt.text(5, 5, "don't use jet!", color='white')


exact = g(xtest, ytest)

import scipy.ndimage.interpolation as spndint
ndint0 = spndint.map_coordinates(array, [it, ir], order=0)
ndint1 = spndint.map_coordinates(array, [it, ir], order=1)
ndint2 = spndint.map_coordinates(array, [it, ir], order=2)

import scipy.interpolate as spint
points = np.vstack((Xp.flatten(), Yp.flatten())).T   # could use np.array(zip(...))
grid_x = xtest
grid_y = np.array([0.75])

g0 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='nearest')
g1 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='linear')
g2 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='cubic')


plt.subplot(4,2,5)

plt.plot(exact, 'or')
#plt.plot(ndint0)
plt.plot(ndint1)
plt.plot(ndint2)
plt.title("map_coordinates")

plt.subplot(4,2,6)

plt.plot(exact, 'or')
#plt.plot(g0)
plt.plot(g1)
plt.plot(g2)
plt.title("griddata")

plt.subplot(4,2,7)

#plt.plot(ndint0 - exact)
plt.plot(ndint1 - exact)
plt.plot(ndint2 - exact)
plt.title("error map_coordinates")

plt.subplot(4,2,8)

#plt.plot(g0 - exact)
plt.plot(g1 - exact)
plt.plot(g2 - exact)
plt.title("error griddata")

plt.show()


seed_points_rand = 2.0 * np.random.random((400, 2))
rr = np.sqrt((seed_points_rand**2).sum(axis=-1))
thth = np.arctan2(seed_points_rand[...,1], seed_points_rand[...,0])
isinside = (rr>r_min) * (rr<r_max) * (thth>theta_min) * (thth<theta_max)
points_rand = seed_points_rand[isinside]

Xprand, Yprand = points_rand.T  # unpack
array_rand = g(Xprand, Yprand)

grid_x = xtest
grid_y = np.array([0.75])

plt.figure()

plt.subplot(2,1,1)

plt.scatter(100.0*Xprand.flatten(), 100.0*Yprand.flatten())
plt.plot(100.0*xtest, 100.0*ytest, '-k', linewidth=3)
plt.hold
plt.imshow(blob, origin='lower', cmap='gray')
plt.text(5, 5, "don't use jet!", color='white')


g0rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='nearest')
g1rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='linear')
g2rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='cubic')

plt.subplot(4,2,6)

plt.plot(exact, 'or')
#plt.plot(g0rand)
plt.plot(g1rand)
plt.plot(g2rand)
plt.title("griddata")


plt.subplot(4,2,8)

#plt.plot(g0rand - exact)
plt.plot(g1rand - exact)
plt.plot(g2rand - exact)
plt.title("error griddata")

plt.show()

非结构化数据:

import numpy as np
import matplotlib.pyplot as plt

def g(x, y):
    return np.exp(-((x-1.0)**2 + (y-1.0)**2))

def findit(x, X):  # or could use some 1D interpolation
    fraction = (x - X[0]) / (X[-1]-X[0])
    return fraction * float(X.shape[0]-1)

nth, nr = 12, 11
theta_min, theta_max = 0.2, 1.3
r_min,     r_max     = 0.7, 2.0

theta = np.linspace(theta_min, theta_max, nth)
r     = np.linspace(r_min,     r_max,     nr)

R, TH = np.meshgrid(r, theta)
Xp, Yp  = R*np.cos(TH), R*np.sin(TH)
array = g(Xp, Yp)

x, y = np.linspace(0.0, 2.0, 200), np.linspace(0.0, 2.0, 200)
X, Y = np.meshgrid(x, y)
blob = g(X, Y)

xtest = np.linspace(0.25, 1.75, 40)
ytest = np.zeros_like(xtest) + 0.75

rtest = np.sqrt(xtest**2 + ytest**2)
thetatest = np.arctan2(xtest, ytest)

ir = findit(rtest, r)
it = findit(thetatest, theta)

plt.figure()

plt.subplot(2,1,1)

plt.scatter(100.0*Xp.flatten(), 100.0*Yp.flatten())
plt.plot(100.0*xtest, 100.0*ytest, '-k', linewidth=3)
plt.hold
plt.imshow(blob, origin='lower', cmap='gray')

plt.text(5, 5, "don't use jet!", color='white')


exact = g(xtest, ytest)

import scipy.ndimage.interpolation as spndint
ndint0 = spndint.map_coordinates(array, [it, ir], order=0)
ndint1 = spndint.map_coordinates(array, [it, ir], order=1)
ndint2 = spndint.map_coordinates(array, [it, ir], order=2)

import scipy.interpolate as spint
points = np.vstack((Xp.flatten(), Yp.flatten())).T   # could use np.array(zip(...))
grid_x = xtest
grid_y = np.array([0.75])

g0 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='nearest')
g1 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='linear')
g2 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='cubic')


plt.subplot(4,2,5)

plt.plot(exact, 'or')
#plt.plot(ndint0)
plt.plot(ndint1)
plt.plot(ndint2)
plt.title("map_coordinates")

plt.subplot(4,2,6)

plt.plot(exact, 'or')
#plt.plot(g0)
plt.plot(g1)
plt.plot(g2)
plt.title("griddata")

plt.subplot(4,2,7)

#plt.plot(ndint0 - exact)
plt.plot(ndint1 - exact)
plt.plot(ndint2 - exact)
plt.title("error map_coordinates")

plt.subplot(4,2,8)

#plt.plot(g0 - exact)
plt.plot(g1 - exact)
plt.plot(g2 - exact)
plt.title("error griddata")

plt.show()


seed_points_rand = 2.0 * np.random.random((400, 2))
rr = np.sqrt((seed_points_rand**2).sum(axis=-1))
thth = np.arctan2(seed_points_rand[...,1], seed_points_rand[...,0])
isinside = (rr>r_min) * (rr<r_max) * (thth>theta_min) * (thth<theta_max)
points_rand = seed_points_rand[isinside]

Xprand, Yprand = points_rand.T  # unpack
array_rand = g(Xprand, Yprand)

grid_x = xtest
grid_y = np.array([0.75])

plt.figure()

plt.subplot(2,1,1)

plt.scatter(100.0*Xprand.flatten(), 100.0*Yprand.flatten())
plt.plot(100.0*xtest, 100.0*ytest, '-k', linewidth=3)
plt.hold
plt.imshow(blob, origin='lower', cmap='gray')
plt.text(5, 5, "don't use jet!", color='white')


g0rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='nearest')
g1rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='linear')
g2rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='cubic')

plt.subplot(4,2,6)

plt.plot(exact, 'or')
#plt.plot(g0rand)
plt.plot(g1rand)
plt.plot(g2rand)
plt.title("griddata")


plt.subplot(4,2,8)

#plt.plot(g0rand - exact)
plt.plot(g1rand - exact)
plt.plot(g2rand - exact)
plt.title("error griddata")

plt.show()

可怕的python:

import numpy as np
import matplotlib.pyplot as plt

def g(x, y):
    return np.exp(-((x-1.0)**2 + (y-1.0)**2))

def findit(x, X):  # or could use some 1D interpolation
    fraction = (x - X[0]) / (X[-1]-X[0])
    return fraction * float(X.shape[0]-1)

nth, nr = 12, 11
theta_min, theta_max = 0.2, 1.3
r_min,     r_max     = 0.7, 2.0

theta = np.linspace(theta_min, theta_max, nth)
r     = np.linspace(r_min,     r_max,     nr)

R, TH = np.meshgrid(r, theta)
Xp, Yp  = R*np.cos(TH), R*np.sin(TH)
array = g(Xp, Yp)

x, y = np.linspace(0.0, 2.0, 200), np.linspace(0.0, 2.0, 200)
X, Y = np.meshgrid(x, y)
blob = g(X, Y)

xtest = np.linspace(0.25, 1.75, 40)
ytest = np.zeros_like(xtest) + 0.75

rtest = np.sqrt(xtest**2 + ytest**2)
thetatest = np.arctan2(xtest, ytest)

ir = findit(rtest, r)
it = findit(thetatest, theta)

plt.figure()

plt.subplot(2,1,1)

plt.scatter(100.0*Xp.flatten(), 100.0*Yp.flatten())
plt.plot(100.0*xtest, 100.0*ytest, '-k', linewidth=3)
plt.hold
plt.imshow(blob, origin='lower', cmap='gray')

plt.text(5, 5, "don't use jet!", color='white')


exact = g(xtest, ytest)

import scipy.ndimage.interpolation as spndint
ndint0 = spndint.map_coordinates(array, [it, ir], order=0)
ndint1 = spndint.map_coordinates(array, [it, ir], order=1)
ndint2 = spndint.map_coordinates(array, [it, ir], order=2)

import scipy.interpolate as spint
points = np.vstack((Xp.flatten(), Yp.flatten())).T   # could use np.array(zip(...))
grid_x = xtest
grid_y = np.array([0.75])

g0 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='nearest')
g1 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='linear')
g2 = spint.griddata(points, array.flatten(), (grid_x, grid_y), method='cubic')


plt.subplot(4,2,5)

plt.plot(exact, 'or')
#plt.plot(ndint0)
plt.plot(ndint1)
plt.plot(ndint2)
plt.title("map_coordinates")

plt.subplot(4,2,6)

plt.plot(exact, 'or')
#plt.plot(g0)
plt.plot(g1)
plt.plot(g2)
plt.title("griddata")

plt.subplot(4,2,7)

#plt.plot(ndint0 - exact)
plt.plot(ndint1 - exact)
plt.plot(ndint2 - exact)
plt.title("error map_coordinates")

plt.subplot(4,2,8)

#plt.plot(g0 - exact)
plt.plot(g1 - exact)
plt.plot(g2 - exact)
plt.title("error griddata")

plt.show()


seed_points_rand = 2.0 * np.random.random((400, 2))
rr = np.sqrt((seed_points_rand**2).sum(axis=-1))
thth = np.arctan2(seed_points_rand[...,1], seed_points_rand[...,0])
isinside = (rr>r_min) * (rr<r_max) * (thth>theta_min) * (thth<theta_max)
points_rand = seed_points_rand[isinside]

Xprand, Yprand = points_rand.T  # unpack
array_rand = g(Xprand, Yprand)

grid_x = xtest
grid_y = np.array([0.75])

plt.figure()

plt.subplot(2,1,1)

plt.scatter(100.0*Xprand.flatten(), 100.0*Yprand.flatten())
plt.plot(100.0*xtest, 100.0*ytest, '-k', linewidth=3)
plt.hold
plt.imshow(blob, origin='lower', cmap='gray')
plt.text(5, 5, "don't use jet!", color='white')


g0rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='nearest')
g1rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='linear')
g2rand = spint.griddata(points_rand, array_rand.flatten(), (grid_x, grid_y), method='cubic')

plt.subplot(4,2,6)

plt.plot(exact, 'or')
#plt.plot(g0rand)
plt.plot(g1rand)
plt.plot(g2rand)
plt.title("griddata")


plt.subplot(4,2,8)

#plt.plot(g0rand - exact)
plt.plot(g1rand - exact)
plt.plot(g2rand - exact)
plt.title("error griddata")

plt.show()
将numpy导入为np
将matplotlib.pyplot作为plt导入
def g(x,y):
返回np.exp(-(x-1.0)**2+(y-1.0)**2))
def findit(x,x):#或者可以使用一些1D插值
分数=(x-x[0])/(x[-1]-x[0])
返回分数*float(X.shape[0]-1)
n,nr=12,11
最小θ,最大θ=0.2,1.3
r_最小值,r_最大值=0.7,2.0
θ=np.linspace(θ最小,θ最大,n)
r=np.linspace(r_最小值、r_最大值、nr)
R、 TH=np.meshgrid(R,θ)
Xp,Yp=R*np.cos(TH),R*np.sin(TH)
数组=g(Xp,Yp)
x、 y=np.linspace(0.0,2.0,200),np.linspace(0.0,2.0,200)
十、 Y=np.meshgrid(X,Y)
blob=g(X,Y)
xtest=np.linspace(0.25,1.75,40)
ytest=np.类零(xtest)+0.75
rtest=np.sqrt(xtest**2+ytest**2)
测试=np.arctan2(xtest,ytest)
ir=findit(rtest,r)
it=findit(thetatest,theta)
plt.图()
plt.子地块(2,1,1)
plt.scatter(100.0*Xp.flatte(),100.0*Yp.flatte())
plt.绘图(100.0*xtest,100.0*ytest,'-k',线宽=3)
等待
plt.imshow(blob,origin='lower',cmap='gray')
plt.text(5,5,“不要使用喷射器!”,color='white')
精确=g(xtest,ytest)
导入scipy.ndimage.interpolation作为spndint
ndint0=spndint.map_坐标(数组,[it,ir],顺序=0)
ndint1=spndint.map_坐标(数组,[it,ir],顺序=1)
ndint2=spndint.map_坐标(数组,[it,ir],顺序=2)
导入scipy.interpolate作为微调
points=np.vstack((Xp.flatte(),Yp.flatte())。T#可以使用np.array(zip(…)
网格x=xtest
网格y=np.数组([0.75])
g0=spint.griddata(点,数组.flatte(),(网格x,网格y),方法='nearest')
g1=spint.griddata(点,数组.展平(),(网格x,网格y),方法='linear')
g2=spint.griddata(点,数组。展平(),(网格x,网格y),方法='cubic')
plt.子地块(4,2,5)
plt.绘图(精确的“或”)
#plt.绘图(ndint0)
plt.绘图(ndint1)
plt.绘图(ndint2)
打印标题(“地图坐标”)
plt.子地块(4,2,6)
plt.绘图(精确的“或”)
#平面图(g0)
平面图(g1)
平面图(g2)
打印标题(“网格数据”)
plt.子地块(4,2,7)
#plt.绘图(ndint0-精确)
plt.绘图(ndint1-精确)
plt.绘图(ndint2-精确)
plt.title(“错误地图坐标”)
plt.子地块(4,2,8)
#plt.绘图(g0-精确)
plt.绘图(g1-精确)
plt.绘图(g2-精确)
plt.title(“错误数据”)
plt.show()
种子点随机=2.0*np.random.random((400,2))
rr=np.sqrt(种子点和**2.sum(轴=-1))
thth=np.arctan2(种子点随机数[…,1],种子点随机数[…,0])
isinside=(rr>r_min)*(rrtheta_min)*(第四个好问题!)

对于非结构化数据,您需要切换回用于非结构化数据的函数。
griddata
是一个选项,但在两者之间使用带线性插值的三角剖分。这会在三角形边界处产生“硬”边

样条曲线是径向基函数。用简单的术语来说,你需要。我建议在三次样条曲线上使用
function=“linear”
function=“thin\u plate”
,但也可以使用三次样条曲线。(与线性或薄板样条曲线相比,三次样条曲线会加剧“过冲”问题。)

需要注意的是,这种特定的径向基函数实现将始终使用数据集中的所有点。这是最准确、最平滑的方法,但随着输入观察点数量的增加,它的伸缩性很差。有几种方法可以解决这个问题,但事情会变得更复杂。我将把它留给另一个任务离子

无论如何,这里有一个简化的示例。我们将生成随机数据,然后在规则网格上的点处对其进行插值。(请注意,输入不在规则网格上,并且插值点也不需要在规则网格上。)


样条曲线类型的选择 我选择了
“薄板”
作为样条线的类型。我们的输入观测点范围从0到1(它们由
np.random.random
)创建)。请注意,我们的插值略高于1,远低于0。这是“超调”


线性样条曲线将完全避免过冲,但最终会出现“牛眼”模式(但远没有IDW方法那么严重)。例如,以下是使用线性径向基函数插值的完全相同的数据。请注意,我们的插值值永远不会超过1或低于0:


高阶样条曲线将使数据的趋势更连续,但会产生更大的超调。默认的
“多重二次曲线”
与薄板样条曲线非常相似,但会使情况更连续,超调更严重:


但是,当您转到更高阶的样条曲线时,例如
“cubic”
(三阶):

“五次方”
(五次方)

你真的可以用