matplotlib 中的曲面图

2025-01-17 09:23:00
admin
原创
116
摘要:问题描述:我有一个 3 元组列表,表示 3D 空间中的一组点。我想绘制一个覆盖所有这些点的表面。plot_surface包中的函数需要mplot3d将 X、Y 和 Z 作为二维数组作为参数。plot_surface该函数是否适合绘制表面?我该如何将数据转换为所需的格式?data = [(x1,y1,z1),(...

问题描述:

我有一个 3 元组列表,表示 3D 空间中的一组点。我想绘制一个覆盖所有这些点的表面。

plot_surface包中的函数需要mplot3d将 X、Y 和 Z 作为二维数组作为参数。plot_surface该函数是否适合绘制表面?我该如何将数据转换为所需的格式?

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

解决方案 1:

对于表面,它与 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()

3D

解决方案 2:

您可以直接从某些文件读取数据并进行绘图

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()

如果需要,您可以传递 vmin 和 vmax 来定义颜色条范围,例如

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

表面

奖金部分

我想知道如何制作一些交互式图表,在这种情况下使用人工数据

from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
from IPython.display import Image

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

def f(x, y):
    return np.sin(np.sqrt(x ** 2 + y ** 2))

def plot(i):

    fig = plt.figure()
    ax = plt.axes(projection='3d')

    theta = 2 * np.pi * np.random.random(1000)
    r = i * np.random.random(1000)
    x = np.ravel(r * np.sin(theta))
    y = np.ravel(r * np.cos(theta))
    z = f(x, y)

    ax.plot_trisurf(x, y, z, cmap='viridis', edgecolor='none')
    fig.tight_layout()

interactive_plot = interactive(plot, i=(2, 10))
interactive_plot

解决方案 3:

我刚刚遇到了同样的问题。我有均匀分布的数据,这些数据位于 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')

这是原始示例。添加下一位将从 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()

得出的数据如下:

在此处输入图片描述
在此处输入图片描述

解决方案 4:

顺便说一句,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()

以下是最终的输出:

xyz 数据的 plot_trisurf

解决方案 5:

这不是一个通用的解决方案,但可能会对那些刚刚在 Google 中输入“matplotlib 表面图”并到达这里的人有所帮助。

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

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

IT科技

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

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()

IT科技

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

解决方案 6:

只是想补充一些可能对其他有不规则域类型问题的人有帮助的想法。对于用户有三个向量/列表的情况,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()

上述代码产生:

非矩形网格问题的表面图

但是,这可能无法解决所有问题,特别是当问题定义在不规则域上时。此外,在域具有一个或多个凹面区域的情况下,德劳内三角剖分可能会导致在域外部生成虚假三角形。在这种情况下,必须从三角剖分中移除这些虚假三角形才能获得正确的表面表示。对于这些情况,用户可能必须明确包含德劳内三角剖分计算,以便可以通过编程方式移除这些三角形。在这种情况下,以下代码可以替换之前的绘图代码:


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()

下面给出了示例图,说明了解决方案 1)存在伪三角形,以及 2)伪三角形已被移除的情况:

在此处输入图片描述

移除三角形

我希望以上内容能够对那些在解决方案数据中遇到凹度情况的人有所帮助。

解决方案 7:

查看官方示例。X、Y 和 Z 确实是二维数组,numpy.meshgrid() 是一种从一维 x 和 y 值中获取二维 x、y 网格的简单方法。

http://matplotlib.sourceforge.net/mpl_examples/mplot3d/surface3d_demo.py

这里是将 3 元组转换为 3 个 1d 数组的 Python 方法。

data = [(1,2,3), (10,20,30), (11, 22, 33), (110, 220, 330)]
X,Y,Z = zip(*data)
In [7]: X
Out[7]: (1, 10, 11, 110)
In [8]: Y
Out[8]: (2, 20, 22, 220)
In [9]: Z
Out[9]: (3, 30, 33, 330)

这是 mtaplotlib delaunay 三角剖分(插值),它将 1d x、y、z 转换为符合要求的内容(?):

http://matplotlib.sourceforge.net/api/mlab_api.html#matplotlib.mlab.griddata

解决方案 8:

在 Matlab 中,我做了类似的事情,仅使用delaunay上的函数(而不是),然后使用或绘图,用作高度。x`yztrimeshtrisurfz`

SciPy 具有Delaunay类,它基于与 Matlabdelaunay函数相同的底层 QHull 库,因此您应该获得相同的结果。

从那里,应该有几行代码将这个在 python-matplotlib 中绘制 3D 多边形的示例转换为您希望实现的目标,因为它Delaunay为您提供了每个三角形多边形的规格。

解决方案 9:

无法直接使用您的数据制作 3D 表面。我建议您使用pykridge等工具构建插值模型。该过程将包括三个步骤:

  1. 使用以下方法训练插值模型pykridge

  2. 构建网格XY使用meshgrid

  3. 插入值Z

创建网格和相应的Z值后,您就可以开始使用了plot_surface。请注意,根据数据的大小,该meshgrid函数可能会运行一段时间。解决方法是使用和轴创建均匀分布的样本np.linspaceX然后Y应用插值来推断必要的Z值。如果是这样,插值可能与原始值不同,Z因为XY已经改变。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用