programing

표면도:매트플롯립

skycolor 2023. 8. 25. 23:26
반응형

표면도:매트플롯립

3D 공간의 점 집합을 나타내는 3-튜플 목록이 있습니다.저는 이 모든 점을 포함하는 표면을 그려보고 싶습니다.

plot_surface에서 합니다.mplot3d패키지는 인수 X, Y 및 Z가 2d 배열이어야 합니다.plot_surface표면도면을 그리는 올바른 기능과 데이터를 필요한 형식으로 변환하는 방법은 무엇입니까?

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

표면의 경우 3-튜플 목록과 약간 다르므로 2D 배열의 도메인에 대한 그리드를 전달해야 합니다.

있는 기능이 포인트의 일 경우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

일부 파일 및 플롯에서 직접 데이터를 읽을 수 있습니다.

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)

surface

보너스 섹션

저는 인공 데이터를 사용하여 대화형 플롯을 수행하는 방법이 궁금합니다.

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

저는 방금 같은 문제를 발견했습니다.2-D 어레이 대신 31-D 어레이에 있는 균일한 간격의 데이터가 있습니다.matplotlibplot_surface제자는우도히연에 .pandas.DataFrame여기 31-D 배열을 플롯하기 위한 수정 사항이 있는 예제가 있습니다.

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

그것이 원래의 예입니다.이 다음 비트를 추가하면 31-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()

다음은 결과 수치입니다.

enter image description here enter image description here

마침 이매뉴얼은 제가 (아마도 많은 다른 사람들도) 찾고 있는 답을 가지고 있었습니다.3D 분산 데이터가 3개의 개별 어레이에 있는 경우 판다는 다른 옵션보다 훨씬 효과적이며 매우 유용합니다.자세히 설명하자면, x, y, z가 임의 변수라고 가정합니다.저의 경우 지원 벡터 머신을 테스트하고 있었기 때문에 c, 감마 및 오류가 발생했습니다.데이터를 표시할 수 있는 옵션은 여러 가지가 있습니다.

  • scatter3D(cParams, gamma, avg_errors_array) - 이것은 작동하지만 지나치게 단순합니다.
  • plot_wireframe(cParams, gammas, avg_errors_array) - 이것은 작동하지만, 실제 과학 데이터의 대량 청크의 경우와 같이 데이터가 잘 정렬되지 않으면 보기 흉할 것입니다.
  • ax.plot3D(cParams, 감마, avg_errors_array) - 와이어프레임과 유사

데이터의 와이어프레임 그림

Wireframe plot of the data

데이터의 3차원 산포

3d scatter of the data

코드는 다음과 같습니다.

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

다음은 최종 출력입니다.

plot_trisurf of xyz data

이것은 일반적인 해결책은 아니지만 구글에서 "matplotlib 표면도"를 입력하고 여기에 착륙한 많은 사람들에게 도움이 될 수 있습니다.

있다고 가정해 보겠습니다.data = [(x1,y1,z1),(x2,y2,z2),.....,(xn,yn,zn)]그러면 다음을 사용하여 3개의 1-D 목록을 얻을 수 있습니다.x, y, z = zip(*data)이제 3개의 1-D 리스트를 사용하여 3D 산점도를 만들 수 있습니다.

그러나 일반적으로 이 데이터를 표면도를 만드는 데 사용할 수 없는 이유는 무엇입니까?빈 3-D 그림을 고려하는 방법:

이제 "이산적인" 정규 그리드에서 (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()

(x, y)의 모든 가능한 조합에 대해 z가 없으면 어떻게 됩니까?그런 다음 점(위의 빈 플롯에서 x-y 평면의 두 검은색 선이 교차하는 지점)에서 z의 값이 무엇인지 알 수 없습니다.무엇이든 될 수 있습니다. 우리는 그 지점에서 우리의 표면이 어떻게 '높음' 또는 '낮음'이어야 하는지 모릅니다(다른 함수를 사용하여 근사할 수 있지만,surface_plotX.shape = Y.shape = Z.shape)에서 변수를 입력해야 합니다.

불규칙한 도메인 유형 문제를 가진 다른 사람들을 도울 수 있는 몇 가지 생각을 추가하기 위해서입니다.사용자가 3개의 벡터/목록, z가 사각형 그리드에 표면으로 표시되는 2D 솔루션을 나타내는 x,y,z가 있는 상황에서는 ArtixR의 '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()

위의 코드는 다음을 생성합니다.

Surface plot for non-rectangular grid problem

그러나 모든 문제, 특히 문제가 불규칙한 도메인에 정의된 경우 이 문제가 해결되지 않을 수 있습니다.또한 도메인에 하나 이상의 오목한 영역이 있는 경우, 지연 삼각 측량은 도메인 외부에 가짜 삼각형을 생성할 수 있습니다.이러한 경우 정확한 표면 표현을 달성하려면 삼각 측량에서 이러한 불량 삼각형을 제거해야 합니다.이러한 상황에서 사용자는 이러한 삼각형을 프로그래밍 방식으로 제거할 수 있도록 지연 삼각형 계산을 명시적으로 포함해야 할 수 있습니다.이러한 상황에서 다음 코드가 이전 플롯 코드를 대체할 수 있습니다.


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) 제거된 위치를 보여주는 아래와 같습니다.

enter image description here

triangles removed

위의 내용이 솔루션 데이터의 오목한 상황에 있는 사람들에게 도움이 되었으면 합니다.

공식 예제를 확인하십시오. X, Y 및 Z는 실제로 2d 배열입니다. numpy.meshgrid()는 1d x 및 y 값에서 2d x,y 메시를 얻는 간단한 방법입니다.

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

여기 3-튜플을 31d 배열로 변환하는 파이썬적인 방법이 있습니다.

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)

다음은 mtapplotlib delaunay 삼각 측량(보간)으로, 1d x, y, z를 호환되는 것(?)으로 변환합니다.

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

Matlab에서 저는 비슷한 것을 했습니다.delaunay에 대한 기능.x,y좌표만(가 아님)z), 다음으로 그림을 표시합니다.trimesh또는trisurf,사용.z높이만큼

SciPy에는 Delaunay 클래스가 있으며, 이 클래스는 Matlab의 클래스와 동일한 기본 QHull 라이브러리를 기반으로 합니다.delaunay함수는 동일한 결과를 얻어야 합니다.

거기서부터, 파이썬-매트플롯립에서 3D 폴리곤을 당신이 성취하고자 하는 것으로 변환하는 것은 코드의 몇 줄이어야 합니다.Delaunay각 삼각형 폴리곤의 사양을 제공합니다.

데이터를 사용하여 3D 표면을 직접 만들 수는 없습니다.저는 당신이 pykridge와 같은 도구를 사용하여 보간 모델을 구축하는 것을 추천합니다.이 프로세스에는 세 가지 단계가 포함됩니다.

  1. 다음을 사용하여 보간 모델 교육pykridge
  2. 다음에서 그리드 구축X그리고.Y사용.meshgrid
  3. 다음에 대한 값 보간Z

그리드 및 해당 그리드를 작성한 경우Z가치관, 이제 당신은 함께 할 준비가 되었습니다.plot_surface참고로 데이터의 크기에 따라meshgrid기능이 잠시 동안 실행될 수 있습니다.해결 방법은 다음을 사용하여 균일한 간격으로 샘플을 생성하는 것입니다.np.linspace위해서X그리고.Y축을 선택한 다음 보간을 적용하여 필요한 값을 추론합니다.Z만약 원래의 보간된 값.ZX그리고.Y변했습니다.

언급URL : https://stackoverflow.com/questions/9170838/surface-plots-in-matplotlib

반응형