2D-интерполяция Python / Scipy (неоднородные данные) - PullRequest
16 голосов
/ 28 февраля 2011

Это дополнительный вопрос к моему предыдущему сообщению: Интерполяция Python / Scipy (map_coordinates)

Допустим, я хочу интерполировать по 2-й прямоугольной области. Моя переменная 'z' содержит данные, как показано ниже. Каждый столбец имеет постоянное значение, однако каждая строка массива может иметь другое значение, как показано в комментарии ниже.

from scipy import interpolate
from numpy import array
import numpy as np
#                                               # 0.0000, 0.1750, 0.8170, 1.0000
z = array([[-2.2818,-2.2818,-0.9309,-0.9309],   # 0.0000, 0.0000, 0.0000, 0.0000
           [-2.2818,-2.2818,-0.9309,-0.9309],   # 0.2620, 0.2784, 0.3379, 0.3526
           [-1.4891,-1.4891,-0.5531,-0.5531],   # 0.6121, 0.6351, 0.7118, 0.7309
           [-1.4891,-1.4891,-0.5531,-0.5531]])  # 1.0000, 1.0000, 1.0000, 1.0000
# Rows, Columns = z.shape

cols = array([0.0000, 0.1750, 0.8170, 1.0000])
rows = array([0.0000, 0.2620, 0.6121, 1.0000])

sp = interpolate.RectBivariateSpline(rows, cols, z, kx=1, ky=1, s=0)

xi = np.array([0.00000, 0.26200, 0.27840, 0.33790, 0.35260, 0.61210, 0.63510,
               0.71180, 0.73090, 1.00000], dtype=np.float)
yi = np.array([0.000, 0.167, 0.815, 1.000], dtype=np.float)
print sp(xi, yi)

Как еще один способ визуализации этого, массив значений, которые Я ЗНАЮ, будет:

rows = array([0.0000, 0.2620, 0.2784, 0.3379, 0.3526,
                      0.6121, 0.6351, 0.7118, 0.7309, 1.0000])
#          # 0.0000, 0.1750, 0.8170, 1.0000
z = array([[-2.2818,-2.2818,-0.9309,-0.9309],   # 0.0000
           [-2.2818,      ?,      ?,      ?],   # 0.2620,
           [      ?,-2.2818,      ?,      ?],   # 0.2784
           [      ?,      ?,-0.9309,      ?],   # 0.3379
           [      ?      ,?,      ?,-0.9309],   # 0.3526
           [-1.4891,      ?,      ?,      ?],   # 0.6121
           [      ?,-1.4891,      ?,      ?],   # 0.6351
           [      ?,      ?,-0.5531,      ?],   # 0.7118
           [      ?,      ?,      ?,-0.5531],   # 0.7309
           [-1.4891,-1.4891,-0.5531,-0.5531]])  # 1.0000

Я не знаю '?' значения, и они должны быть интерполированы. Я попытался заменить их на None, но затем получил 'nan' для всех моих результатов.

EDIT:

Я думаю, что мне нужно использовать либо griddata, либо interp2. Кажется, что griddata дает результат, которого я ожидаю, а 'interp2' - нет.

from scipy import interpolate
from numpy import array
import numpy as np

z = array([[-2.2818,-2.2818,-0.9309,-0.9309],
           [-2.2818,-2.2818,-0.9309,-0.9309],
           [-1.4891,-1.4891,-0.5531,-0.5531],
           [-1.4891,-1.4891,-0.5531,-0.5531]])

rows = array([0.0000, 0.0000, 0.0000, 0.0000,
              0.2620, 0.2784, 0.3379, 0.3526,
              0.6121, 0.6351, 0.7118, 0.7309,
              1.0000, 1.0000, 1.0000, 1.0000])

cols = array([0.0000, 0.1750, 0.8180, 1.0000,
              0.0000, 0.1750, 0.8180, 1.0000,
              0.0000, 0.1750, 0.8180, 1.0000,
              0.0000, 0.1750, 0.8180, 1.0000])

xi = array([0.0000, 0.2620, 0.2784, 0.3379, 0.3526, 0.6121, 0.6351, 0.7118,
               0.7309, 1.0000], dtype=np.float)
yi = array([0.000, 0.175, 0.818, 1.000], dtype=np.float)

GD = interpolate.griddata((rows, cols), z.ravel(),
                          (xi[None,:], yi[:,None]), method='linear')
I2 = interpolate.interp2d(rows, cols, z, kind='linear')

print GD.reshape(4, 10).T
print '\n'
print I2(xi, yi).reshape(4, 10).T

import matplotlib.pyplot as plt
import numpy.ma as ma

plt.figure()
GD = interpolate.griddata((rows.ravel(), cols.ravel()), z.ravel(),
                          (xi[None,:], yi[:,None]), method='linear')
CS = plt.contour(xi,yi,GD,15,linewidths=0.5,colors='k')
CS = plt.contourf(xi,yi,GD,15,cmap=plt.cm.jet)
plt.colorbar()
plt.scatter(rows,cols,marker='o',c='b',s=5)

plt.figure()
I2 = I2(xi, yi)
CS = plt.contour(xi,yi,I2,15,linewidths=0.5,colors='k')
CS = plt.contourf(xi,yi,I2,15,cmap=plt.cm.jet)
plt.colorbar()
plt.scatter(rows,cols,marker='o',c='b',s=5)
plt.show()

1 Ответ

16 голосов
/ 28 февраля 2011

Похоже, вы получили это.

В верхнем примере кода и в предыдущем ( связанный ) вопросе у вас есть структурированные данные.Который может быть интерполирован с помощью RectBivariateSpline или interp2d.Это означает, что у вас есть данные, которые можно описать на сетке (все точки на сетке имеют известное значение).Сетка не обязательно должна иметь одинаковые dx и dy.(если бы все dx и dy были равны, у вас была бы регулярная сетка)

Теперь ваш текущий вопрос спрашивает, что делать, если не все точки известны.Это известно как неструктурированные данные.Все, что у вас есть, это выбор точек в поле.Вы не можете обязательно построить прямоугольники, где все вершины имеют известные значения.Для этого типа данных вы можете использовать (как у вас есть) griddata или разновидность BivariateSpline.

Теперь, что выбрать?

Ближайшая аналогия со структурированной RectBivariateSpline является одним из неструктурированных BivariateSpline классов : SmoothBivariateSpline или LSQBivariateSpline.Если вы хотите использовать сплайны для интерполяции данных, используйте их.это делает вашу функцию гладкой и дифференцируемой, но вы можете получить поверхность, которая выходит за пределы Z.max () или Z.min ().

Так как вы устанавливаете ky=1 и kx=1 и получаете то, чтоЯ почти уверен, что это просто линейная интерполяция для структурированных данных , лично я бы просто переключился со схемы сплайна RectBivariateSpline на interp2d структурированные схема интерполяции сетки.Я знаю, что документация говорит, что это для обычных сеток , но пример в самом __doc__ является только структурированным , а не обычным.

Мне было бы любопытно, если бы вы нашли какие-либо существенные различия между методами, если бы вы в конечном итоге переключились.Добро пожаловать в SciPy.

...