首页 > 解决方案 > Matplotlib -3D 数据可视化

问题描述

这是一个txt文件的示例

我的实验测量在几个 txt 文件中(实际上我会有数百个文件,但为了演示绘图的想法,这里我只列出了 3 个文件,它们是 d_401.txt、d_402.txt、d_403.txt)每个文件有 4 列和 256 行数据。(只有第一列和第四列是我需要的 x 和 z 数据)

我想从这些文件中绘制一个 3D 曲面图/或等高线图。在 My 3D plot 中,x 轴普遍是每个文件的第 1 列数据,z 轴是每个文件的第 4 列数据(z 值也需要在渐变中进行颜色编码),最后 y 轴是“从这三个文件中绘制的所有 xz 值的 y 方向排列”。

如何为这个情节生成 python 代码?我特别困惑如何分配矩阵 Z,如果有人能在这个问题上帮助我,我将不胜感激......我需要尽快绘制这个数字。

我附上了我的未成熟(据说充满了错误代码)

太感谢了!!!

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

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

z_txt = np.array(['d_401.txt', 'd_402.txt', 'd_403.txt'])

zarray = np.zeros([z_txt.size])
y = np.arange(3)
x = np.zeros(256)
Z = np.zeros((len(y),len(x)))


for i in range(z_txt.size):
    zarray[i] = np.loadtxt(z_txt[i])
    x[i] = zarray[i,0]
    X, Y = np.meshgrid(x,y)
    Z[i] = zarray[i,3]
ax.plot_surface(X, Y, Z, cmap=cm.magma, shade=True, lw=3)

plt.show()

标签: pythonnumpymatplotlibplot

解决方案


以下假设所有文件都包含相同的x向量……</p>

In [146]: import numpy as np
     ...: import matplotlib.pyplot as plt
     ...: from matplotlib.cm import ScalarMappable as sm
     ...: from glob import glob
     ...: 
     ...: # create fake data and put it in files
     ...: x0, y0 = np.arange(11.0), np.arange(3)+1.0
     ...: z0 = x0+y0[:,None]
     ...: for i in range(3):
     ...:     with open('delendo%d'%(i+1), 'w') as out:
     ...:         for x0z0 in zip(x0, x0+x0, x0-x0, z0[i]):
     ...:             print(*x0z0, sep='\t', file=out)
     ...: 
     ...: # sorted list of "interesting" files
     ...: files = sorted(glob('delendo*'))
     ...: 
     ...: # read the matrix of z values
     ...: Z = np.array([np.loadtxt(f, usecols=3) for f in files])
     ...: # read the vector of x values (the same for all files, I hope so!)
     ...: x = np.loadtxt(files[0], usecols=0)
     ...: # we have as many y's as rows in Z, and we count from 1
     ...: y = np.arange(Z.shape[0])+1
     ...: 
     ...: # prepare for a 3D plot and plot as a surface
     ...: fig, ax = plt.subplots(constrained_layout=1,
     ...:                        subplot_kw={"projection" : "3d"})
     ...: surf = ax.plot_surface(*np.meshgrid(x,y), Z, cmap='magma')
     ...: norm = plt.Normalize(*surf.get_clim())
     ...: plt.colorbar(sm(norm=norm, cmap='magma'))
     ...: plt.show()

在此处输入图像描述


附录

解决OP评论中提出的一些问题

你问*sequence运营商。它是unpack运算符,可以在赋值或表达式中使用。让我们来看看

>>> tup = (1,2,3,4,5)
>>> a = tup ; print(a)
(1, 2, 3, 4, 5)
>>> a, b = tup
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

但是如果你使用解包操作符

>>> a, *b = tup ; print(a, b)
1 [2, 3, 4, 5]

Python 理解这b是一个序列,并在这个序列中存储剩余的元素tup——顺便说一下,b它是一个列表而不是一个元组。

unpack 运算符可以用在 left 成员的中间,但只能使用一次,因为 Python 将剩余的内容分配给带星号的项目,两个星号的项目会导致歧义。

>>> a,*b, c = tup ; print(a, b, c)
1 [2, 3, 4] 5
>>> a,*b, *c = tup ; print(a, b, c)
  File "<stdin>", line 1
SyntaxError: multiple starred expressions in assignment

现在,让我们看看 unpack 运算符在表达式中的作用

>>> print(*b)
2 3 4 

使用星号语法解包列表,就像

>>> print(b[0], b[1], b[2])
2 3 4

现在,谈到您的问题,您已经在代码中使用了解包。即使你可能不知道......</p>

    X, Y = np.meshgrid(x,y)

来到我的代码

surf = ax.plot_surface(*np.meshgrid(x,y), Z, cmap='magma')

在这一点上应该很清楚,我们正在解包返回的内容meshgrid,这就像网格数组( )没有被引用并且它们使用的内存可以立即返回给解释器X, Y = meshgrid(...) ; surf = ...(X, Y, Z, ...)的(小)优势一样。X, Y

关于您的最后一点,要创建颜色条 Matplotlib 需要所谓的标量可映射(sm),并且plt.colorbar可以检查活动轴以查看是否有 sm 挂在附近。
许多艺术家(吸引到 Axes 的软件代理)喜欢imshow创建一个 sm,一切都很好,但plot_surface不会,所以可怜的程序员必须提供一个手工制作的 sm 到colorbar.
要指定 sm,我们需要①一个规范和②一个颜色图。
规范是默认值,即 ,plt.Normalize我们需要 的限制,Z这些是 的值surf.get_clim(),我再次使用星号语法来解包这两个值。

这个解释的长度是首先省略它的理由......</p>


推荐阅读