我有一组坐标(x,y和z),用于描述人脸的表面。数据类型是pandas数据框,并且数据按z坐标的切片进行排序。我想对数据进行排序,以便将其分隔在网格中。
我是编程新手,所以我没有尝试很多事情。我真的不知道从哪里开始或如何解决这个问题。下面的图片可视化了我正在使用的数据。Picture to visualize data
我无法分享我正在使用的确切数据。我生成了一组数据,这些数据代表我正在使用的数据。数据生成如下所示:
import numpy as np
import matplotlib.pyplot as plt
plt.figure()
ax = plt.axes(projection="3d")
plt.xlabel('X')
plt.ylabel('Y')
ax.set_zlabel('Z')
(x, y) = np.meshgrid(np.arange(-2, 2.1, .1), np.arange(-1, 1.1, .1))
z = 3*x**3-2*y**2
x = x.ravel()
y = y.ravel()
z = z.ravel()
ax.plot3D(x, y, z, linestyle = '', marker ='.')
我希望将数据相对于x和z轴分隔在网格中,以便将数据分隔在不同的数组中。
编辑:我要如何分离数据的可视化:visualization of the result I want
从图中,您希望网格位于x-z平面中。然后,我们可以从讨论中忽略y值。您没有指定有关网格大小的任何内容。假设是通常,我们可以创建两个数组,分别表示网格块之间的分隔线(对于您的数据,值将有所不同)。请注意,我已将np.inf添加为最后一个元素。
grid_x_lim = np.concatenate([np.arange(-1.5, 1.6, 0.5), [np.inf]])
grid_z_lim = np.concatenate([np.arange(-20, 21, 10), [np.inf]])
[想法是x坐标低于-1.5的任何点都在第一条垂直线的左侧,而z坐标低于-20的任何点都在第一条水平线的下方,依此类推。
对于下面的示例数据(来自您的示例代码)
plt.figure()
ax = plt.axes(projection="3d")
plt.xlabel('X')
plt.ylabel('Y')
ax.set_zlabel('Z')
(x, y) = np.meshgrid(np.arange(-2, 2.1, .1), np.arange(-1, 1.1, .1))
z = 3*x**3-2*y**2
x = x.ravel()
y = y.ravel()
z = z.ravel()
ax.plot3D(x, y, z, linestyle = '', marker ='.')
plt.show()
我们得到(仅在此处绘制x-z坐标)
fig, ax = plt.subplots(1,1)
for x_coord in grid_x_lim[:-1]: # Plot vertical lines
ax.axvline(x_coord)
for z_coord in grid_z_lim[:-1]: # Plot horizontal lines
ax.axhline(z_coord)
ax.plot(x, z, ".") # We are only ploting the x-z values
ax.set_xlabel("x")
ax.set_ylabel("z")
plt.show()
该图看起来很好,但是我们仍然需要将数据分离到网格中。现在我们使用grid_x_lim
和grid_z_lim
在原始数据中的每个点处找到网格中的索引。
x_idx = np.argmax(x < grid_x_lim[:, np.newaxis], axis=0)
z_idx = np.argmax(z < grid_z_lim[:, np.newaxis], axis=0)
由于您需要线性索引而不是两个索引,因此可以使用
linear_idx = z_idx * grid_z_lim.size + x_idx
此linear_idx
变量与x
,y
和z
变量具有相同的尺寸,它指示点落在网格中的块的索引。让我们检查一下它是否起作用。我们可以重复之前的情节,但是我们会用不同的颜色绘制每个块中的点。
fig, ax = plt.subplots(1, 1)
for x_coord in grid_x_lim[:-1]:
ax.axvline(x_coord)
for z_coord in grid_z_lim[:-1]:
ax.axhline(z_coord)
colors = ["red", "green", "cyan", "blue", "magenta"]
color_idx = 0
for i in range(grid_x_lim.size * grid_z_lim.size):
desired_linear_idx = i # Change this to different values and check the plot
mask = linear_idx == desired_linear_idx
if(sum(mask) > 0):
ax.plot(x[mask], z[mask], ".", color=colors[color_idx])
color_idx = (color_idx + 1) % len(colors)
ax.set_xlabel("x")
ax.set_ylabel("z")
plt.show()
注:线性索引从左下角开始,从左到右依次从下到上递增。但是,如果您确实需要从左上角开始调整代码,应该很容易。