3D空間の点のセットを表す3タプルのリストがあります。これらすべてのポイントをカバーするサーフェスをプロットしたいと思います。
パッケージ内のplot_surface関数では、mplot3d引数としてX、Y、およびZが2次元配列である必要があります。表面をプロットするための正しい関数はありますか?plot_surfaceデータを必要な形式に変換するにはどうすればよいですか?
data = [(x1,y1,z1),(x2,y2,z2),.....,(xn,yn,zn)]
3D空間の点のセットを表す3タプルのリストがあります。これらすべてのポイントをカバーするサーフェスをプロットしたいと思います。
パッケージ内のplot_surface関数では、mplot3d引数としてX、Y、およびZが2次元配列である必要があります。表面をプロットするための正しい関数はありますか?plot_surfaceデータを必要な形式に変換するにはどうすればよいですか?
data = [(x1,y1,z1),(x2,y2,z2),.....,(xn,yn,zn)]
サーフェスの場合、3 タプルのリストとは少し異なります。ドメインのグリッドを 2 次元配列で渡す必要があります。
関数ではなく 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()

この同じ問題に遭遇しました。必要な 2 次元配列ではなく、3 つの 1 次元配列に等間隔のデータがありmatplotlibますplot_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()
結果の数値は次のとおりです。

不規則なドメインタイプの問題で他の人を助けるかもしれないいくつかの考えを追加するだけです. ユーザーが 3 つのベクトル/リスト (x、y、z) を持っている状況では、z が面として長方形のグリッドにプロットされる 2D ソリューションを表し、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()
上記のコードは以下を生成します。
ただし、これですべての問題が解決されるわけではありません。特に、問題が不規則なドメインで定義されている場合はそうです。また、ドメインに 1 つまたは複数の凹面領域がある場合、ドロネー三角形分割により、ドメインの外側に偽の三角形が生成される可能性があります。このような場合、正しいサーフェス表現を実現するために、これらの不正な三角形を三角形分割から削除する必要があります。これらの状況では、これらの三角形をプログラムで削除できるように、ユーザーはドローネ三角形分割の計算を明示的に含める必要がある場合があります。このような状況では、次のコードで前のプロット コードを置き換えることができます。
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) それらが削除された場合:
上記が、ソリューション データに凹みのある状況にある人々の助けになることを願っています。
公式の例を確認してください。X、Y、Z は確かに 2 次元配列です。numpy.meshgrid() は、1 次元の x 値と y 値から 2 次元の x、y メッシュを取得する簡単な方法です。
http://matplotlib.sourceforge.net/mpl_examples/mplot3d/surface3d_demo.py
これは、3 タプルを 3 つの 1 次元配列に変換する Pythonic な方法です。
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