Как я могу интерполировать отсутствующие значения (неопределенные области) 3D-графика поверхности (2D-массив) с помощью Python? - PullRequest
1 голос
/ 03 июля 2019

В Python 3.7 с использованием Numpy и matplotlib я хотел бы построить трехмерную поверхность для следующего уравнения:

f(x,y)=sin(x)sin(y)/(x*y)

Эта функция явно не определена, где x = 0 или y = 0 .

Для вычисления и построения графика у меня есть следующий код, который я сейчас выполняю в блокноте Jupyter:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib notebook

f = lambda x, y: np.sin(x)*np.sin(y)/(x*y)

xs, ys = np.mgrid[-np.pi:np.pi:31j, -np.pi:np.pi:31j]
zs = f(xs, ys)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot_surface(X=xs, Y=ys, Z=zs)

Обратите внимание на график, в котором отсутствуют значения: enter image description here

Как я могу интерполировать пропущенные значения, чтобы график выглядел гладким?

Ответы [ 2 ]

1 голос
/ 03 июля 2019

В этом конкретном случае вы можете использовать scipy.special.sinc. Это вставляет точный результат sin(0)/0 = 1:

import numpy as np
from scipy.special import sinc
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib notebook

f = lambda x, y: sinc(x)*sinc(y)

xs, ys = np.mgrid[-1:1:31j, -1:1:31j]
zs = f(xs, ys)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot_surface(X=xs*np.pi, Y=ys*np.pi, Z=zs)

enter image description here

1 голос
/ 03 июля 2019

У Сципи есть модуль интерполяции, который может сделать это. Исходя из вышеизложенного (при публикации вопроса), этот код можно запустить в следующей ячейке:

from scipy import interpolate

# integer arrays for indexing
x_indx, y_indx = np.meshgrid(np.arange(0, zs.shape[1]),
                             np.arange(0, zs.shape[0]))

# mask all invalid values
zs_masked = np.ma.masked_invalid(zs)

# retrieve the valid, non-Nan, defined values
valid_xs = x_indx[~zs_masked.mask]
valid_ys = y_indx[~zs_masked.mask]
valid_zs = zs_masked[~zs_masked.mask]

# generate interpolated array of z-values
zs_interp = interpolate.griddata((valid_xs, valid_ys), valid_zs.ravel(),
                                 (x_indx, y_indx), method='cubic')

# finally, plot the data 
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.plot_surface(X=xs, Y=ys, Z=zs_interp)

Возвращается следующий график: enter image description here

Обратите внимание, что этот код оптимизирован для удобочитаемости и понятности, а не эффективности памяти. Повторная оптимизация этого кода для повышения эффективности памяти является тривиальной задачей, которая остается на усмотрение читателя

...