我正在尝试用 python 创建一座山的表面图,其中我有一些 xyz 数据。最终结果应该类似于 。文件格式如下:
616000.0 90500.0 3096.712
616000.0 90525.0 3123.415
616000.0 90550.0 3158.902
616000.0 90575.0 3182.109
616000.0 90600.0 3192.991
616025.0 90500.0 3082.684
616025.0 90525.0 3116.597
616025.0 90550.0 3149.812
616025.0 90575.0 3177.607
616025.0 90600.0 3191.986
等等。第一列代表
x
坐标,中间的 y
坐标,z
属于 xy 坐标的高度。
我使用
pandas
读取数据,然后将列转换为单独的 x
、y
、z
NumPy
一维数组。到目前为止,我设法创建了一个简单的 3D 散点图,其中使用 for
循环迭代每个 1D 数组的每个索引,但这需要很长时间,并且看起来效率相当低。
我尝试使用
scipy.interpolate.griddata
和 plt.plot_surface
,但对于 z
数据,我总是收到数据应该位于 2D 数组中的错误,但我无法弄清楚为什么或如何它应该是 2D 数据。我假设给定我有 xyz 数据,应该有一种方法可以简单地从中创建一个表面。有没有简单的方法?
使用 plot_trisurf
中的函数
scatter
和
matplotlib
,给定 X Y Z
数据可以类似于 进行绘制。
import sys
import csv
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
# Read CSV
csvFileName = sys.argv[1]
csvData = []
with open(csvFileName, 'r') as csvFile:
csvReader = csv.reader(csvFile, delimiter=' ')
for csvRow in csvReader:
csvData.append(csvRow)
# Get X, Y, Z
csvData = np.array(csvData)
csvData = csvData.astype(np.float)
X, Y, Z = csvData[:,0], csvData[:,1], csvData[:,2]
# Plot X,Y,Z
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(X, Y, Z, color='white', edgecolors='grey', alpha=0.5)
ax.scatter(X, Y, Z, c='red')
plt.show()
这里,
X Y Z
数据的文件plot_trisurf
中,用于控制外观的参数。例如alpha
用于控制表面的不透明度scatter
中,c
参数指定在曲面上绘制的点的颜色对于给定的数据文件,生成以下图表
注意: 这里,地形是通过给定的一组 3D 点进行三角测量而形成的。因此,图中沿表面的轮廓未与 X 轴和 Y 轴对齐
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
import pandas as pd
df = pd.read_csv("/content/1.csv")
X = df.iloc[:, 0]
Y = df.iloc[:, 1]
Z = df.iloc[:, 2]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(X, Y, Z, color='white', edgecolors='grey', alpha=0.5)
ax.scatter(X, Y, Z, c='red')
plt.show()
有一种更简单的方法可以在不使用 pandas 的情况下实现你的目标。
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
x, y = np.mgrid[-2 : 2 : 20j, -2 : 2 : 20j]
z = 50 * np.sin(x + y) # test data
output = plt.subplot(111, projection = '3d') # 3d projection
output.plot_surface(x, y, z, rstride = 2, cstride = 1, cmap = plt.cm.Blues_r)
output.set_xlabel('x') # axis label
output.set_xlabel('y')
output.set_xlabel('z')
plt.show()