Создание графиков сетки в Plotly с неквадратными массивами X, Y, Z в Python

Я строю сферу с тремя квадратными массивами x, y и z. Форма каждого массива равна (100 100) (то есть x.shape = (100, 100)), и я могу построить поверхность с помощью Plotly:

import numpy as np
import plotly.graph_objs as go
from plotly.offline import plot

r = 1000
u, v = np.mgrid[0:2 * np.pi:100j, 0:np.pi:100j]
x = np.cos(u) * np.sin(v)
y = np.sin(u) * np.sin(v)
z = np.cos(v)

# Plotting layout
titlecolor = 'white'
bgcolor = 'black'
noaxis = dict(showbackground=False, showgrid=False, showline=False, 
              showticklabels=False, ticks='', title='', zeroline=False)

layout = go.Layout(autosize=True,
         titlefont = dict(family='Courier New', color=titlecolor),
         showlegend = False,
         scene = dict(xaxis=noaxis, yaxis=noaxis, zaxis=noaxis,
                      aspectmode='auto'),
         paper_bgcolor = bgcolor,
         plot_bgcolor = bgcolor)

fig = go.Figure(data=go.Surface(x=x, y=y, z=z, opacity=0.2), layout=layout)
plot(fig, validate = False, auto_open=True)

который производит

Но теперь, скажем, я не хочу показывать всю сферу — вместо этого я хочу удалить точки, где Z > 0,8, и показать эту форму. Я делаю это, сглаживая x, y и z, находя индексы в z, где z>0.8, и удаляя эти индексы из всех трех массивов:

# Remove points where z > 0.8
x,y,z = [i.flatten() for i in [X,Y,Z]]
rmvidx = np.where(z>0.8)
x = [np.delete(x,j) for j in rmvidx][0]
y = [np.delete(y,j) for j in rmvidx][0]
z = [np.delete(z,j) for j in rmvidx][0]
# Add in new axis
x = x[:,np.newaxis]
y = y[:,np.newaxis]
z = z[:,np.newaxis]

Теперь каждый массив имеет форму (7900,1); кроме того, np.sqrt(7900)=88.8819, поэтому одномерные массивы нельзя преобразовать в квадратные массивы без добавления или дальнейшего удаления точек.

Я хочу создать аналогичную поверхность из этих точек. Если я попытаюсь использовать тот же метод построения графика (go.Surface), ничего не отобразится, и go.Mesh3d:

fig = go.Figure(data=go.Mesh3d(x=x, y=y, z=z, opacity=0.2), layout=layout)

также создает пустое изображение без поверхности. Как я могу использовать Plotly для отображения трехмерной поверхности для одномерных массивов, аналогично тому, что я смог создать для сферы?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если вы имеете в виду поверхности, определенные x, y z формы (m, n), где m ≠ n, и go.Surface, и go.Mesh3d работают так же, как и в случае с формой (m, m):

import numpy as np
from numpy import pi, sin, cos
u = np.linspace(0, 1, 50)
v = np.linspace(0, 2*pi, 100)
u, v = np.meshgrid(u,v)
x = u*cos(v)
y = u*sin(v)
z = u**2
#x, y z are of shape  (100, 50)
fig = go.Figure(go.Surface(x=x, y=y, z=z))

или как триангулированная поверхность:

import numpy as np
from numpy import pi, sin, cos
from scipy.spatial import Delaunay
u = np.linspace(0, 1, 50)
v = np.linspace(0, 2*pi, 100)
u, v = np.meshgrid(u,v) #u, v have shape(100, 50)
u1,v1 = u.flatten(),v.flatten()
points2D=np.vstack([u1,v1]).T
x = u1*cos(v1)
y = u1*sin(v1)
z = u1**2
tri= Delaunay(points2D)
i, j, k = tri.simplices.T
fig = go.Figure(go.Mesh3d(x=x, y=y, z=z, i=i, j=j, k=k,intensity=z))

Если вы имеете в виду другой случай, пожалуйста, приведите минимальный пример.

По вашему запросу я обновил свой исходный вопрос с минимальным примером.

AaronJPung 21.04.2023 15:35
Ответ принят как подходящий

Во-первых, кажется, что вы используете старую версию Plotly. Более простой код, который работает с любой версией, выпущенной начиная с 2020 года:

import numpy as np
import plotly.graph_objects as go

u, v = np.mgrid[0:2 * np.pi:100j, 0:np.pi:100j]
x = np.cos(u) * np.sin(v)
y = np.sin(u) * np.sin(v)
z = np.cos(v)
axes_off=dict(xaxis_visible=False, yaxis_visible=False, zaxis_visible=False)
fig = go.Figure(go.Surface(x=x, y=y, z=z, colorscale = "matter_r"))
fig.update_scenes(dict(**axes_off))
fig.show()

Вместо того, чтобы удалять некоторые элементы, просто отключите их настройку на np.nan:

z[np.where(z>0.8)]=np.nan
fignew=go.Figure(go.Surface(x=x, y=y, z=z, colorscale = "matter_r"))
fignew.update_scenes(dict(**axes_off))
fignew.update_layout(width=500, height=500, font_size=11)

Второе: для установки новой версии ploly используйте команду:

pip install plotly --upgrade

Другие вопросы по теме