给定三个X,Y和Z坐标的1D阵列,如何使用numpy转换为3D网格路径?
我设法使用numpy为2D做了这个(即没有for循环):
import numpy
def path_2d_numpy(x, y):
m1, m2 = numpy.meshgrid(x, y)
m1[1::2] = m1[1::2,::-1]
r = numpy.append(m1, m2)
r.shape = 2,-1
return r.T
from matplotlib import lines
from matplotlib import pyplot
def plot_path_2d(path):
x, y = path.T
pyplot.plot(x, y, '-ro', lw=3)
pyplot.show()
x = numpy.linspace(4, 1, 4)
y = numpy.linspace(1, 5, 5)
path = path_2d_numpy(x, y)
plot_path_2d(path)
输出:
...但是无法为3D做到这一点。显示纯python解决方案(即没有numpy):
import numpy
def path_3d(x, y, z):
nb_points =len(x)*len(y)*len(z)
path = numpy.empty((nb_points, 3))
xord, yord, i = True, True, 0
for zi in z:
for yi in y[::1 if yord else -1]:
for xi in x[::1 if xord else -1]:
path[i] = xi, yi, zi
i += 1
xord = not xord
yord = not yord
return path
from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D
def plot_path_3d(path):
fig = pyplot.figure()
ax = fig.gca(projection='3d')
xx, yy, zz = path.T
ax.plot(xx, yy, zz, '-bo', lw=3)
pyplot.show()
x = numpy.linspace(4, 1, 4)
y = numpy.linspace(1, 5, 5)
z = numpy.linspace(-3, 0, 3)
path = path_3d(x, y, z)
plot_path_3d(path)
输出:
Essencialy,我正在寻找的是 path_3d 的numpy实现,正如我为 path_2d_numpy 所做的那样。
我需要这个,因为我正在处理的实际数组非常大。没有numpy这样做太慢了。
答案 0 :(得分:6)
这看起来怎么样?
import numpy as np
def path_3d_numpy(x, y, z):
coords = np.stack(np.meshgrid(x, y, z), axis=-1) # shape = (nx, ny, nz, 3)
coords[1::2,:,:] = coords[1::2,::-1,:]
coords[:,1::2,:] = coords[:,1::2,::-1]
return coords.reshape(-1, 3) # flatten out the other axes
不会以与你的顺序相同的顺序迭代这些点,但你可以简单地通过交换一些索引来解决这个问题
同样,您的2d案例可以写成
def path_2d_numpy(x, y):
coords = np.stack(np.meshgrid(x, y), axis=-1)
coords[1::2] = coords[1::2,::-1]
return coords.reshape(-1, 2)
对于某些真正的矫枉过正,您可以将其扩展为N维:
def path_nd(*args):
coords = np.stack(np.meshgrid(*args), axis=-1)
N = len(args)
axes = np.arange(N)
for i in range(N-1):
# the last axis isn't part of our mesh, so don't roll it
rolled_axes = tuple(np.roll(axes, -i)) + (N,)
rolled_view = np.transpose(coords, rolled_axes)
rolled_view[1::2,:] = rolled_view[1::2,::-1]
return coords.reshape(-1, N)