Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
342 views
in Technique[技术] by (71.8m points)

python - Scipy interpolation on a numpy array

I have a lookup table that is defined the following way:

       | <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] ])
  • The header row elements are (hh) < 1,2,3,4,5+
  • The header column (inc) elements are <10000, 20000, 20001+

The user will input a value example (1.3, 25,000), (0.2, 50,000), so on. scipy.interpolate() should interpolate to determine the correct value.

Currently, the only way I can do this is with a bunch of if/elifs as exemplified below. I'm pretty sure there is a better, more efficient way of doing this

Here's what I've got so far:

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]) )
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Edit: Updated things to reflect your clarifications above. Your question is much clearer now, thanks!

Basically, you're just wanting to interpolate a 2D array at an arbitrary point.

scipy.ndimage.map_coordinates is what you want....

As I understand your question, you have a 2D array of "z" values that ranges from some xmin to xmax, and ymin to ymax in each direction.

Anything outside of those bounding coordinates you want to return values from the edges of the array.

map_coordinates has several options to handle points outside the boundaries of the grid, but none of them do exactly what you want. Instead, we can just set anything outside the boundaries to lie on the edge, and use map_coordinates as usual.

So, to use map_coordinates, you need to turn your actual coodinates:

       | <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

Into index coordinates:

       |  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

Note that your boundaries behave differently in each direction... In the x-direction, things behave smoothly, but in the y-direction, you're asking for a "hard" break, where y=20000 --> 3.9, but y=20000.000001 --> 4.5.

As an example:

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

This yields:

1.3 , 25000 --> 5.1807375
0.2 , 50000 --> 4.5
2.5 , 15000 --> 8.12252371652

Hopefully that helps...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...