简体   繁体   中英

How can I interpolate missing values (undefined areas) of a 3D surface plot (2D array) using Python?

In Python 3.7 using Numpy and matplotlib, I would like to plot a 3D surface for the following equation:

F(X,Y)=的sin(x)SIN(Y)/(X * Y)

This function is obviously undefined where x=0 or y=0 .

To calculate and plot this, I have the following code, which I am currently running in a Jupyter Notebook:

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)

Notice the graph, which is missing values: 在此处输入图片说明

How can I interpolate the missing values so that the graph appears smooth?

Scipy has an interpolation module that can do this. Relying on the above (in the question posting), this code can be run in the next cell:

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)

The following graph is returned: 在此处输入图片说明

Note that this code has been optimized for readability and comprehensibility rather than memory efficiency. Re-Optimizing this code for memory efficiency is a trivial task that is left up to the reader

In this specific case, you can use scipy.special.sinc . This inserts the exact result 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)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM