matplotlib中的表面图

Gra*_*ddy 95 python matplotlib

我有一个3元组的列表,表示3D空间中的一组点.我想绘制一个覆盖所有这些点的表面.mplot3d包中的plot_surface函数需要作为参数X,Y和Z,它们是2d数组.plot_surface是绘制曲面的正确函数吗?如何将数据转换为所需格式?

data = [(x1,y1,z1),(x2,y2,z2),.....,(xn,yn,zn)]

wim*_*wim 106

对于曲面,它与3元组列表略有不同,您应该在2d数组中传入域的网格.

如果您拥有的只是一个3d点列表而不是某些函数f(x, y) -> z,那么您将遇到问题,因为有多种方法可以将3d点云三角化为曲面.

这是一个光滑的表面示例:

import numpy as np
from mpl_toolkits.mplot3d import Axes3D  
# Axes3D import has side effects, it enables using projection='3d' in add_subplot
import matplotlib.pyplot as plt
import random

def fun(x, y):
    return x**2 + y

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(-3.0, 3.0, 0.05)
X, Y = np.meshgrid(x, y)
zs = np.array(fun(np.ravel(X), np.ravel(Y)))
Z = zs.reshape(X.shape)

ax.plot_surface(X, Y, Z)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 但是当z是一个自变量而不是x和y的函数时,你会怎么做? (12认同)
  • 这个导入有副作用.在没有这个导入的情况下,在调用`fig.add_subplot`中使用kwarg`projection ='3d'`将不可用. (5认同)
  • 嗨,谢谢你。您能否详细说明如何使用函数 `f(x,y) -> z` 比仅仅使用像 OP 最初使用的列表方法可以获得更多信息。 (2认同)
  • 在这种情况下,也许你应该看一下`plot_trisurf`.但正如我所提到的,这是非常重要的,因为你需要对表面进行三角测量,并且有多种解决方案.作为基本示例,仅考虑由(0,0,0.2),(0,1,0),(1,1,0.2),(1,0,0)给出的4个点.从上面看,它看起来像一个有轻微折叠的正方形.*但沿着哪条对角线出现"折叠"?*是0.2处的"高"对角线还是0处的"低"对角线?两者都是有效的表面!因此,在有明确定义的解决方案之前,您需要选择三角测量算法. (2认同)

Ema*_*les 24

我使用PANDAS在python中使用了一些线条,情节是美丽的!

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from sys import argv

x,y,z = np.loadtxt('your_file', unpack=True)

fig = plt.figure()
ax = Axes3D(fig)
surf = ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.1)
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.savefig('teste.pdf')
plt.show()
Run Code Online (Sandbox Code Playgroud)

如有必要,您可以通过vmin和vmax来定义颜色条范围,例如

surf = ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.1, vmin=0, vmax=2000)
Run Code Online (Sandbox Code Playgroud)

表面

  • 严格来说,这里不需要大熊猫. (5认同)

Ste*_*ell 19

我刚遇到同样的问题.我已经均匀地间隔开的数据是在3 1-d阵列的代替的是,2-d阵列matplotlibplot_surface希望.我的数据碰巧是在一个pandas.DataFrame所以这里是修改绘制3个1-D数组的matplotlib.plot_surface例子.

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
    linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)
plt.title('Original Code')
Run Code Online (Sandbox Code Playgroud)

这是最初的例子.添加下一位会从3个1-D阵列创建相同的图.

# ~~~~ MODIFICATION TO EXAMPLE BEGINS HERE ~~~~ #
import pandas as pd
from scipy.interpolate import griddata
# create 1D-arrays from the 2D-arrays
x = X.reshape(1600)
y = Y.reshape(1600)
z = Z.reshape(1600)
xyz = {'x': x, 'y': y, 'z': z}

# put the data into a pandas DataFrame (this is what my data looks like)
df = pd.DataFrame(xyz, index=range(len(xyz['x']))) 

# re-create the 2D-arrays
x1 = np.linspace(df['x'].min(), df['x'].max(), len(df['x'].unique()))
y1 = np.linspace(df['y'].min(), df['y'].max(), len(df['y'].unique()))
x2, y2 = np.meshgrid(x1, y1)
z2 = griddata((df['x'], df['y']), df['z'], (x2, y2), method='cubic')

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x2, y2, z2, rstride=1, cstride=1, cmap=cm.coolwarm,
    linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)
plt.title('Meshgrid Created from 3 1D Arrays')
# ~~~~ MODIFICATION TO EXAMPLE ENDS HERE ~~~~ #

plt.show()
Run Code Online (Sandbox Code Playgroud)

以下是结果数字:

在此输入图像描述 在此输入图像描述


Dee*_*eep 8

这不是一个通用的解决方案,但可能会帮助许多刚刚在 Google 中输入“matplotlib 曲面图”并登陆此处的人。

假设你有data = [(x1,y1,z1),(x2,y2,z2),.....,(xn,yn,zn)],那么你可以使用 得到三个一维列表x, y, z = zip(*data)。现在您当然可以使用三个一维列表创建 3d 散点图。

但是,为什么通常不能使用这些数据来创建曲面图?要理解这一点,请考虑一个空的 3 维图:

现在,假设对于“离散”规则网格上 (x, y) 的每个可能值,您都有 az 值,那么就没有问题了,您实际上可以获得曲面图:

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

x = np.linspace(0, 10, 6)  # [0, 2,..,10] : 6 distinct values
y = np.linspace(0, 20, 5)  # [0, 5,..,20] : 5 distinct values
z = np.linspace(0, 100, 30)  # 6 * 5 = 30 values, 1 for each possible combination of (x,y)

X, Y = np.meshgrid(x, y)
Z = np.reshape(z, X.shape)  # Z.shape must be equal to X.shape = Y.shape

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

ax.plot_surface(X, Y, Z)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
Run Code Online (Sandbox Code Playgroud)

当你没有得到 (x, y) 所有可能组合的 z 时会发生什么?然后在该点(上面空白图上 xy 平面上两条黑线的交点处),我们不知道 z 的值是多少。它可以是任何东西,我们不知道此时我们的表面应该有多“高”或“低”(尽管可以使用其他函数来近似,但surface_plot需要您提供参数,其中 X.shape = Y.shape = Z.形状)。


Art*_*exR 5

顺便插一句,Emanuel 得到了我(可能还有很多其他人)正在寻找的答案。如果您在 3 个单独的数组中有 3d 分散的数据,pandas 是一个令人难以置信的帮助,并且比其他选项工作得更好。详细说明,假设您的 x,y,z 是一些任意变量。就我而言,这些是 c、gamma 和错误,因为我正在测试支持向量机。绘制数据有许多潜在的选择:

  • scatter3D(cParams, gammas, avg_errors_array) - 这有效但过于简单
  • plot_wireframe(cParams, gammas, avg_errors_array) - 这有效,但如果你的数据没有很好地排序,看起来会很难看,因为大量真实的科学数据可能就是这种情况
  • ax.plot3D(cParams, gammas, avg_errors_array) - 类似于线框

数据的线框图

数据的线框图

数据的 3d 散点图

数据的 3d 散点图

代码如下所示:

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.set_xlabel('c parameter')
    ax.set_ylabel('gamma parameter')
    ax.set_zlabel('Error rate')
    #ax.plot_wireframe(cParams, gammas, avg_errors_array)
    #ax.plot3D(cParams, gammas, avg_errors_array)
    #ax.scatter3D(cParams, gammas, avg_errors_array, zdir='z',cmap='viridis')

    df = pd.DataFrame({'x': cParams, 'y': gammas, 'z': avg_errors_array})
    surf = ax.plot_trisurf(df.x, df.y, df.z, cmap=cm.jet, linewidth=0.1)
    fig.colorbar(surf, shrink=0.5, aspect=5)    
    plt.savefig('./plots/avgErrs_vs_C_andgamma_type_%s.png'%(k))
    plt.show()
Run Code Online (Sandbox Code Playgroud)

这是最终的输出:

xyz 数据的 plot_trisurf


Gra*_*m G 5

只是添加一些进一步的想法,这可能会帮助其他人解决不规则的域类型问题。对于用户具有三个向量/列表的情况,x,y,z 表示 2D 解决方案,其中 z 将作为表面绘制在矩形网格上,ArtifixR 的“plot_trisurf()”注释适用。一个类似但非矩形域的示例是:

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D 

# problem parameters
nu = 50; nv = 50
u = np.linspace(0, 2*np.pi, nu,) 
v = np.linspace(0, np.pi, nv,)

xx = np.zeros((nu,nv),dtype='d')
yy = np.zeros((nu,nv),dtype='d')
zz = np.zeros((nu,nv),dtype='d')

# populate x,y,z arrays
for i in range(nu):
  for j in range(nv):
    xx[i,j] = np.sin(v[j])*np.cos(u[i])
    yy[i,j] = np.sin(v[j])*np.sin(u[i])
    zz[i,j] = np.exp(-4*(xx[i,j]**2 + yy[i,j]**2)) # bell curve

# convert arrays to vectors
x = xx.flatten()
y = yy.flatten()
z = zz.flatten()

# Plot solution surface
fig = plt.figure(figsize=(6,6))
ax = Axes3D(fig)
ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0,
                antialiased=False)
ax.set_title(r'trisurf example',fontsize=16, color='k')
ax.view_init(60, 35)
fig.tight_layout()
plt.show()
Run Code Online (Sandbox Code Playgroud)

上面的代码产生:

非矩形网格问题的曲面图

但是,这可能无法解决所有问题,尤其是在问题定义在不规则域上的情况下。此外,在域具有一个或多个凹面区域的情况下,delaunay 三角剖分可能会导致在域外部生成伪三角形。在这种情况下,必须从三角剖分中删除这些流氓三角形,以实现正确的表面表示。对于这些情况,用户可能必须明确包含 delaunay 三角剖分计算,以便可以通过编程方式删除这些三角形。在这些情况下,以下代码可以替换之前的绘图代码:


import matplotlib.tri as mtri 
import scipy.spatial
# plot final solution
pts = np.vstack([x, y]).T
tess = scipy.spatial.Delaunay(pts) # tessilation

# Create the matplotlib Triangulation object
xx = tess.points[:, 0]
yy = tess.points[:, 1]
tri = tess.vertices # or tess.simplices depending on scipy version

#############################################################
# NOTE: If 2D domain has concave properties one has to
#       remove delaunay triangles that are exterior to the domain.
#       This operation is problem specific!
#       For simple situations create a polygon of the
#       domain from boundary nodes and identify triangles
#       in 'tri' outside the polygon. Then delete them from
#       'tri'.
#       <ADD THE CODE HERE>
#############################################################

triDat = mtri.Triangulation(x=pts[:, 0], y=pts[:, 1], triangles=tri)

# Plot solution surface
fig = plt.figure(figsize=(6,6))
ax = fig.gca(projection='3d')
ax.plot_trisurf(triDat, z, linewidth=0, edgecolor='none',
                antialiased=False, cmap=cm.jet)
ax.set_title(r'trisurf with delaunay triangulation', 
          fontsize=16, color='k')
plt.show()
Run Code Online (Sandbox Code Playgroud)

下面给出了示例图,说明了解决方案 1) 带有伪三角形,以及 2) 它们已被删除的地方:

在此处输入图片说明

删除了三角形

希望以上内容对解题数据中存在凹陷情况的人有所帮助。


归档时间:

查看次数:

201132 次

最近记录:

6 年,7 月 前