मैटलपोटलिब में सतह भूखंड


104

मेरे पास 3-टुपल्स की एक सूची है जो 3 डी अंतरिक्ष में बिंदुओं के एक सेट का प्रतिनिधित्व करती है। मैं एक सतह तैयार करना चाहता हूं जो इन सभी बिंदुओं को कवर करती है।

plot_surfaceमें समारोह mplot3dपैकेज के रूप में तर्क एक्स, वाई और जेड 2 डी सरणियों होने की आवश्यकता है। क्या plot_surfaceसतह को प्लॉट करने का सही कार्य है और मैं अपने डेटा को आवश्यक प्रारूप में कैसे बदलूं?

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


कृपया उन सभी डुप्लिकेट सतह को टैग करना शुरू करें , और डुप्लिकेट को एक दूसरे में बंद करें। इसके अलावा टैग खस्ता , उन लोगों के लिए मेष जो मेशग्रीड पीढ़ी के बारे में हैं।
smci

जवाबों:


120

सतहों के लिए यह 3-ट्यूपल्स की सूची से थोड़ा अलग है, आपको 2d सरणियों में डोमेन के लिए ग्रिड में पास होना चाहिए।

यदि आपके पास कुछ फ़ंक्शन के बजाय 3 डी बिंदुओं की एक सूची है f(x, y) -> z, तो आपको एक समस्या होगी क्योंकि उस 3 डी बिंदु क्लाउड को एक सतह में त्रिभुज करने के कई तरीके हैं।

यहाँ एक चिकनी सतह उदाहरण है:

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

3 डी


1
हाय, इसके लिए धन्यवाद। क्या आप इस बात के बारे में विस्तार से बता सकते हैं कि किसी समारोह में f(x,y) -> zआपको केवल ओपी की तरह सूची दृष्टिकोण का उपयोग करने की तुलना में अधिक जानकारी मिलती है।
ग्रेगोरी कुह्न

16
लेकिन आप क्या करते हैं जब z एक स्वतंत्र चर है और x और y का कार्य नहीं है?
लबीबा

4
इस मामले में, शायद आपको plot_trisurfइसके बजाय देखना चाहिए । लेकिन जैसा कि मैंने उल्लेख किया है, यह गैर-तुच्छ है क्योंकि आपको सतह को त्रिभुज करने की आवश्यकता है और कई समाधान हैं। एक मूल उदाहरण के रूप में, (0, 0, 0.2), (0, 1, 0), (1, 1, 0.2), (1, 0, 0) द्वारा दिए गए सिर्फ 4 बिंदुओं पर विचार करें। ऊपर से देखने पर यह बस एक वर्ग की तरह दिखता है जिसमें थोड़ी सी तह होती है। लेकिन किस मोड़ के साथ "गुना" होता है? यह 0.2 पर "उच्च" विकर्ण या 0 पर "कम" विकर्ण है? दोनों मान्य सतह हैं! इससे पहले कि आप एक अच्छी तरह से परिभाषित समाधान है, इससे पहले आपको एक त्रिभुज एल्गोरिथ्म चुनना होगा।
विम

Mpl_toolkits.mplot3d से आयात Axes3D क्यों, अभी तक कोड में कहीं भी Axes3D का उपयोग नहीं किया गया है?
絢 絵 里

5
इस आयात के दुष्प्रभाव हैं। Kwarg का उपयोग करते हुए projection='3d'कॉल में fig.add_subplotयह आयात के बिना उपलब्ध नहीं होगा।
विम

33

आप कुछ फ़ाइल और प्लॉट से डेटा डायरेक्ट पढ़ सकते हैं

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

यदि आवश्यक हो तो आप colorbar रेंज को परिभाषित करने के लिए 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

5
कड़ाई से बोलते हुए, पांडा यहां अनावश्यक हैं।
डाउनर

मेरे पास इस कथानक को पुन: पेश करने का कठिन समय है। इसे प्राप्त करने के लिए कुछ (छोटे) नमूना मूल्य क्या होंगे?
JRsz

21

मैं बस इसी समस्या को लेकर आया था। मैं समान रूप से डेटा 2-डी सरणियों के बजाय 3 1-डी सरणियों में है कि स्थान दिया गया है matplotlibकी plot_surfaceआवश्यकताओं। मेरे डेटा में एक हुआ pandas.DataFrameतो यहाँ है matplotlib.plot_surfaceउदाहरण के संशोधनों के साथ 3 1-डी सरणियों प्लॉट करने के लिए।

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-डी सरणियों से एक ही भूखंड बनाया जाता है।

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

यहाँ परिणामी आंकड़े हैं:

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें


मैं सोच रहा था कि क्या सतह पर आने वाली रेखाओं (ऊपर की छवि) को हटाना संभव है, मेरा मतलब है कि सतह को टेढ़ी उपस्थिति के बजाय चमकदार रूप देना संभव है? धन्यवाद। @ stvn66
diffracteD

@diffracteD, एक छोटे ग्रिड आकार का उपयोग करने का प्रयास करें। मैं लगभग निश्चित हूं कि कंट्रोवर्स के बीच की चौड़ाई क्या है। एक महीन ग्रिड पर मूल्यांकन करके, आपको अनिवार्य रूप से "पिक्सेल आकार" को कम करना चाहिए और रिज़ॉल्यूशन को बढ़ाना चाहिए, एक चिकनी ढाल के पास।
स्टीवन सी। हॉवेल

क्या विशिष्ट श्रेणियों के अनुसार उपरोक्त सतह को रंगने का एक तरीका है? पूर्व के लिए। श्रेणी x, y, z डेटा स्वरूप है और मैं किसी विशेष श्रेणी के अनुसार x, y, z से गुजरने वाली सतह को रंग देना चाहूंगा।
रूद्रेश अजगांवकर

@RudreshAjgaonkar, आपको अपनी प्रत्येक श्रेणी के लिए तीन अलग-अलग प्लॉट कमांड का उपयोग करने में सक्षम होना चाहिए, तीनों में से प्रत्येक के लिए आप जो भी रंग चाहते हैं उसका उपयोग कर सकते हैं।
स्टीवन सी। हॉवेल

क्या आप एक नमूना कोड प्रदान कर सकते हैं? मैं matplotlib और अजगर के लिए बहुत नया हूँ।
रुद्रेश अजगांवकर

4

बस झंकार में, एमानुएल का जवाब था कि मैं (और शायद कई अन्य) तलाश कर रहा हूं। यदि आपके पास 3 अलग-अलग सरणियों में 3 डी बिखरा हुआ डेटा है, तो पांडा एक अविश्वसनीय मदद है और अन्य विकल्पों की तुलना में बहुत बेहतर काम करता है। विस्तृत करने के लिए, मान लीजिए कि आपके x, y, z कुछ मनमाना चर हैं। मेरे मामले में ये सी, गामा और त्रुटियां थीं क्योंकि मैं एक समर्थन वेक्टर मशीन का परीक्षण कर रहा था। डेटा को प्लॉट करने के लिए कई संभावित विकल्प हैं:

  • स्कैटर 3 डी (cParams, gammas, avg_errors_array) - यह काम करता है लेकिन अत्यधिक सरल है
  • प्लॉट_वायरफ्रेम (cParams, gammas, avg_errors_array) - यह काम करता है, लेकिन बदसूरत दिखाई देगा यदि आपका डेटा अच्छी तरह से सॉर्ट नहीं किया गया है, जैसा कि वास्तविक वैज्ञानिक डेटा के बड़े पैमाने पर होने की संभावना है
  • ax.plot3D (cParams, gammas, avg_errors_array) - वायरफ्रेम के समान

डेटा के वायरफ्रेम प्लॉट

डेटा के वायरफ्रेम प्लॉट

डेटा का 3 डी बिखराव

डेटा का 3 डी बिखराव

कोड इस तरह दिखता है:

    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


3

आधिकारिक उदाहरण की जाँच करें। X, Y और Z वास्तव में 2d सरणियाँ हैं, numpy.meshgrid () 2d x, y जाल को 1d x और y मानों से बाहर निकालने का एक सरल तरीका है।

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

यहाँ अपने 3-tuples को 3 1d सरणियों में परिवर्तित करने का 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 triangulation (प्रक्षेप) है, यह 1d x, y, z को कुछ आज्ञाकारी (?) में परिवर्तित करता है।

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


नहीं ... XYZ उस उदाहरण में 2-आयामी हैं।
23:10

मुझे सही साबित होना है। यदि आपके डेटा को समान रूप से लिंक किया गया है, तो मेशग्रिड () का उपयोग करें। यदि आपके डेटा में समान रूप से अंतर नहीं है, तो उदाहरण के लिए ग्रिडडेटा () के साथ इंटरपोलेट करें।
दीमा टिस्नेक

1

मतलाब में मैंने कुछ इसी तरह के delaunayफंक्शन का इस्तेमाल किया x, yकोर्डर्स केवल (नहीं z), फिर उसके साथ साजिश रचकर trimeshया trisurfइस्तेमाल करकेz ऊंचाई के रूप में ।

SciPy में Delaunay क्लास है, जो उसी अंतर्निहित QHull लाइब्रेरी पर आधारित है, जो Matlab की हैdelaunay कार्य है, इसलिए आपको समान परिणाम प्राप्त करने चाहिए।

वहां से, इस प्लॉटिंग 3 डी पॉलीगॉन को अजगर-मेटप्लोटलिब उदाहरण में बदलने के लिए कोड की कुछ पंक्तियाँ होनी चाहिए, जिसे आप प्राप्त करना चाहते हैं, जैसा Delaunayकि आप प्रत्येक त्रिकोणीय बहुभुज का विनिर्देश देते हैं।


इस उत्तर पर आधारित देखें ax.plot_trisurf(..)
एवगेनी सर्गेव

1

बस कुछ और विचारों को जोड़ने के लिए जो अनियमित डोमेन प्रकार की समस्याओं के साथ दूसरों की मदद कर सकते हैं। ऐसी स्थिति के लिए जहां उपयोगकर्ता के पास 3 डी / सूची, 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()

उपरोक्त कोड का उत्पादन:

गैर-आयताकार ग्रिड समस्या के लिए सतह की साजिश

हालाँकि, यह सभी समस्याओं को हल नहीं कर सकता है, विशेष रूप से जहां समस्या एक अनियमित डोमेन पर परिभाषित की गई है। इसके अलावा, उस मामले में जहां डोमेन में एक या अधिक अवतल क्षेत्र होते हैं, delaunay त्रिकोण के परिणामस्वरूप डोमेन के लिए बाहरी त्रिभुज बाहरी उत्पन्न हो सकते हैं। ऐसे मामलों में, सही सतह प्रतिनिधित्व प्राप्त करने के लिए इन दुष्ट त्रिकोणों को त्रिकोण से हटाया जाना चाहिए। इन स्थितियों के लिए, उपयोगकर्ता को स्पष्ट रूप से delaunay triangulation गणना को शामिल करना पड़ सकता है ताकि इन त्रिकोणों को प्रोग्रामेटिक रूप से हटाया जा सके। इन परिस्थितियों में, निम्न कोड पिछले प्लॉट कोड को बदल सकता है:


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) जहां उन्हें हटा दिया गया है:

यहां छवि विवरण दर्ज करें

त्रिकोण हटा दिए गए

मुझे उम्मीद है कि उपरोक्त समाधान डेटा में संक्षिप्त स्थितियों वाले लोगों की मदद के लिए हो सकता है।


0

अपने डेटा का उपयोग करके सीधे 3 डी सतह बनाना संभव नहीं है। मैं आपको pykridge जैसे कुछ उपकरणों का उपयोग करके एक प्रक्षेप मॉडल बनाने की सलाह दूंगा । प्रक्रिया में तीन चरण शामिल होंगे:

  1. उपयोग कर एक प्रक्षेप मॉडल को प्रशिक्षित करें pykridge
  2. से Xऔर Yउपयोग कर एक ग्रिड बनाएँmeshgrid
  3. के लिए इंटरपोलेट मान Z

अपना ग्रिड और संबंधित Zमान बनाने के बाद, अब आप साथ जाने के लिए तैयार हैं plot_surface। ध्यान दें कि आपके डेटा के आकार के आधार पर, meshgridफ़ंक्शन थोड़ी देर तक चल सकता है। वर्कअराउंड के np.linspaceलिए Xऔर Yकुल्हाड़ियों का उपयोग करके समान रूप से अंतरित नमूने बनाने के लिए है, फिर आवश्यक Zमानों का अनुमान लगाने के लिए प्रक्षेप लागू करें । यदि हां, तो प्रक्षेपित मूल्य मूल से भिन्न हो सकते हैं Zक्योंकि Xऔर Yबदल गए हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.