在NumPy数组上进行Scipy插值
我有一个查找表,定义如下:
| <1 2 3 4 5+
-------|----------------------------
<10000 | 3.6 6.5 9.1 11.5 13.8
20000 | 3.9 7.3 10.0 13.1 15.9
20000+ | 4.5 9.2 12.2 14.8 18.2
TR_ua1 = np.array([ [3.6, 6.5, 9.1, 11.5, 13.8],
[3.9, 7.3, 10.0, 13.1, 15.9],
[4.5, 9.2, 12.2, 14.8, 18.2] ])
- 表头的元素是 (hh) < 1,2,3,4,5+
- 表头的列元素是 (inc) <10000, 20000, 20001+
用户会输入一些值,比如 (1.3, 25000),(0.2, 50000) 等等。然后需要用 scipy.interpolate()
来进行插值,以确定正确的值。
目前,我只能通过一堆 if
/elif
来实现,下面是我的示例代码。我觉得肯定有更好、更高效的方法来做到这一点。
这是我目前的代码:
import numpy as np
from scipy import interpolate
if (ua == 1):
if (inc <= low_inc): # low_inc = 10,000
if (hh <= 1):
return TR_ua1[0][0]
elif (hh >= 1 & hh < 2):
return interpolate( (1, 2), (TR_ua1[0][1], TR_ua1[0][2]) )
1 个回答
8
编辑:根据你上面的澄清更新了一些内容。你的问题现在清楚多了,谢谢!
基本上,你只是想在一个二维数组的任意点进行插值。
scipy.ndimage.map_coordinates 是你需要的工具……
根据我对你问题的理解,你有一个“z”值的二维数组,这个数组在每个方向上都有一个范围,从xmin到xmax,以及从ymin到ymax。
任何超出这些边界坐标的地方,你希望返回数组边缘的值。
map_coordinates有几种选项可以处理网格边界外的点,但没有一种完全符合你的需求。相反,我们可以简单地把边界外的点视为在边缘,然后像往常一样使用map_coordinates。
所以,要使用map_coordinates,你需要把你的实际坐标:
| <1 2 3 4 5+
-------|----------------------------
<10000 | 3.6 6.5 9.1 11.5 13.8
20000 | 3.9 7.3 10.0 13.1 15.9
20000+ | 4.5 9.2 12.2 14.8 18.2
转换成索引坐标:
| 0 1 2 3 4
-------|----------------------------
0 | 3.6 6.5 9.1 11.5 13.8
1 | 3.9 7.3 10.0 13.1 15.9
2 | 4.5 9.2 12.2 14.8 18.2
注意,你的边界在每个方向上的表现是不同的……在x方向上,变化是平滑的,但在y方向上,你要求的是一个“硬”断裂,比如y=20000对应3.9,但y=20000.000001对应4.5。
举个例子:
import numpy as np
from scipy.ndimage import map_coordinates
#-- Setup ---------------------------
z = np.array([ [3.6, 6.5, 9.1, 11.5, 13.8],
[3.9, 7.3, 10.0, 13.1, 15.9],
[4.5, 9.2, 12.2, 14.8, 18.2] ])
ny, nx = z.shape
xmin, xmax = 1, 5
ymin, ymax = 10000, 20000
# Points we want to interpolate at
x1, y1 = 1.3, 25000
x2, y2 = 0.2, 50000
x3, y3 = 2.5, 15000
# To make our lives easier down the road, let's
# turn these into arrays of x & y coords
xi = np.array([x1, x2, x3], dtype=np.float)
yi = np.array([y1, y2, y3], dtype=np.float)
# Now, we'll set points outside the boundaries to lie along an edge
xi[xi > xmax] = xmax
xi[xi < xmin] = xmin
# To deal with the "hard" break, we'll have to treat y differently,
# so we're ust setting the min here...
yi[yi < ymin] = ymin
# We need to convert these to (float) indicies
# (xi should range from 0 to (nx - 1), etc)
xi = (nx - 1) * (xi - xmin) / (xmax - xmin)
# Deal with the "hard" break in the y-direction
yi = (ny - 2) * (yi - ymin) / (ymax - ymin)
yi[yi > 1] = 2.0
# Now we actually interpolate
# map_coordinates does cubic interpolation by default,
# use "order=1" to preform bilinear interpolation instead...
z1, z2, z3 = map_coordinates(z, [yi, xi])
# Display the results
for X, Y, Z in zip((x1, x2, x3), (y1, y2, y3), (z1, z2, z3)):
print X, ',', Y, '-->', Z
这会得到:
1.3 , 25000 --> 5.1807375
0.2 , 50000 --> 4.5
2.5 , 15000 --> 8.12252371652
希望这能帮到你……