公众号:尤而小屋
作者:Peter
编辑:Peter
大家好,我是Peter~
本文中重点介绍的是如何利用plotly来绘制3D图形。
在3D图形中一般是包含3个轴的:x、y、z。在Plotly中绘图的时候,我们对layout布局进行设置的时候,通常是对一个叫做scene的参数进行设置,在这个参数就是包含x、y、z3个不同轴的设置,比如轴的范围、名称、颜色等。同时还会介绍不同类型的3D图形,比如:3D散点图、3D平面图等
先睹为快
首先我们看看几个由Plotly实现的3D图形,你相信它们其实是同一个吗?
Plotly连载
Plotly目前连载的全部文章如下:
导入库、数据
本文中的很多图形都是基于鸢尾花数据集来绘制的,所以我们先导入库和数据集:
import pandas as pdimport numpy as npimport plotly.express as pximport plotly.graph_objects as go
3D Scatter(3D散点图):基于plotly_express
基本3D图形
最简单的3D图形,通过使用px.scatter_3d来绘制:
fig = px.scatter_3d(iris,x="sepal_length",y="sepal_width",z="petal_width",color="species")fig.show()
设置散点不同的形状和大小;
# 还可以给每个散点加上不同的markder标记fig = px.scatter_3d(iris,x="sepal_length",y="sepal_width",z="petal_length",color="petal_width",symbol="species")fig.show()
# 设置散点大小fig = px.scatter_3d(iris,x="sepal_length",y="sepal_width",z="petal_width",color="petal_length",size="petal_length",size_max=18, # 散点最大值opacity=0.7, # 透明度symbol="species")fig.update_layout(margin=dict(l=0,r=0,b=0,t=0))fig.show()
3D Scatter:基于go.Scatter3dME
基础3D图形
import plotly.graph_objects as goimport numpy as np# 模拟数据t = np.linspace(0, 10, 50)x, y, z = np.cos(t), np.sin(t), tfig = go.Figure(data=[go.Scatter3d(x=x, # 设置3个不同的坐标数据y=y, z=z,mode='markers')]) # 'lines', 'markers', 'text' 3种情况的组合fig.show()
改变散点的颜色:
import plotly.graph_objects as goimport numpy as npN = 88t = np.linspace(0, 20, N)x, y, z = np.cos(t), np.sin(t), tfig = go.Figure(data=[go.Scatter3d(x=x,y=y,z=z,mode='markers',marker=dict( # 对标记的设置size=10,color=z, # 颜色设置colorscale='Viridis', # 选择颜色opacity=0.86 # 透明度))])# 图形的边际范围设置fig.update_layout(margin=dict(l=4, r=4, b=0, t=0))fig.show()
3D平面图:go.Surface实现
基于地形的3D平面图
使用的数据如下:
import plotly.graph_objects as goimport pandas as pd# 读取在线的csv文件z_data = pd.read_csv('/plotly/datasets/master/api_docs/mt_bruno_elevation.csv',index_col=0) # index_col参数表示将第一列的数据当做索引z_data.head()
fig = go.Figure(data=[go.Surface(z=z_data.values)])fig.update_layout(title="3D Surface图形绘制", # 标题autosize=False, # 尺度自动缩放width=700, # 长宽height=600,margin=dict(l=65,r=50,b=65,t=90) # 4个位置的距离)fig.show()
带有轮廓线的3D图形
# 数据同上# 1、先生成画布fig = go.Figure(data=[go.Surface(z=z_data.values)])fig.update_traces(contours_z=dict( # 轮廓设置show=True, # 开启是否显示usecolormap=True, # 颜色设置highlightcolor="mistyrose", # 高亮project_z=True))fig.update_layout(title='带有轮廓的3D平面图',autosize=False,scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64),width=600, height=500,margin=dict(l=65, r=50, b=65, t=90))fig.show()
多个3D图形
在一个画布中国绘制多个图形:
z1 = np.array([ # numpy数组形式[8.83,8.89,8.81,8.87,8.9,8.87],[8.89,8.94,8.85,8.94,8.96,8.92],[8.84,8.9,8.82,8.92,8.93,8.91],[8.79,8.85,8.79,8.9,8.94,8.92],[8.79,8.88,8.81,8.9,8.95,8.92],[8.8,8.82,8.78,8.91,8.94,8.92],[8.75,8.78,8.77,8.91,8.95,8.92],[8.8,8.8,8.77,8.91,8.95,8.94],[8.74,8.81,8.76,8.93,8.98,8.99]])z2 = z1 + 5z3 = z1 - 5fig = go.Figure(data=[go.Surface(z=z1),go.Surface(z=z2, showscale=False, opacity=0.9),go.Surface(z=z3, showscale=False, opacity=0.9)])fig.show()
6 3D气泡图:3D Bubble
6.1 基于Plotly_Express实现
data = px.data.gapminder() # gdp数据集fig = px.scatter_3d(data, # 传入数据x='year', # 选择3个坐标y='continent', z='pop', size='gdpPercap', # 气泡大小color='lifeExp', # 颜色hover_data=['country']) # 悬停数据# 如果数据过大,可以使用对数来表示fig.update_layout(scene_zaxis_type="log") # z轴取对数fig.show()
6.2 基于go.Scatter3d实现
数据部分:
start, end = 800,1200 # 选择开始和结束索引,用于筛选数据fig = go.Figure(data=go.Scatter3d(x=df1['year'][start:end], # 通过设置的数值,切片方式取出部分数据y=df1['continent'][start:end],z=df1['pop'][start:end],text=df1['country'][start:end], # 文本显示的数据mode='markers', # 气泡的显示形式:标记markermarker=dict( sizemode = 'diameter', # 大小的形式:'diameter', 'area'sizeref = 1500,size = df1['gdpPercap'][start:end],color = df1['lifeExp'][start:end],colorscale = 'Viridis',line_color='rgb(140, 140, 170)')))fig.update_layout(height=800, width=800,title='3D气泡图绘制')fig.show()
7 3D等值曲面图(Isosurface)
使用go.Isosurface来绘制
7.1 基础3D等值
import plotly.graph_objects as gofig= go.Figure(data=go.Isosurface(x=[0,0,0,0,1,1,1,1], # 设置3个坐标y=[1,0,1,0,1,0,1,0],z=[1,1,0,0,1,1,0,0],value=[1,2,3,4,5,6,7,8], # 设置取值isomin=2, # 颜色取值范围isomax=7,))fig.show()
7.2 改变等值曲面的个数
在下面的案例中使用了numpy中的一个函数mgrid:
np.mgrid函数返回多维结构,常见的如2D图形,3D图形。对比np.meshgrid,在处理大数据时速度更快,且能处理多维(np.meshgrid只能处理2维)ret = np.mgrid[ 第1维,第2维 ,第3维 , …] :返回多值,以多个矩阵的形式返回,第1返回值为第1维数据在最终结构中的分布,第2返回值为第2维数据在最终结构中的分布,以此类推。
import plotly.graph_objects as goimport numpy as np# 通过numpy的mgrid函数来生成3个数据X, Y, Z = np.mgrid[-5:5:40j, -5:5:40j, -5:5:40j]# 取值values = X * X * 0.5 + Y * Y + Z * Z * 2fig = go.Figure(data=go.Isosurface(x=X.flatten(),y=Y.flatten(),z=Z.flatten(),value=values.flatten(),isomin=10,isomax=50,surface_count=5, colorbar_nticks=5, caps=dict(x_show=False, y_show=False)))fig.show()
改变颜色和透明度
import plotly.graph_objects as goimport numpy as np# 通过numpy的mgrid函数来生成3个数据X, Y, Z = np.mgrid[-5:5:40j, -5:5:40j, -5:5:40j]# 取值values = X * X * 0.5 + Y * Y + Z * Z * 2fig = go.Figure(data=go.Isosurface(x=X.flatten(),y=Y.flatten(),z=Z.flatten(),value=values.flatten(),opacity=0.6, # 改变图形的透明度colorscale='plotly3', # 改变颜色isomin=10,isomax=50,surface_count=5, colorbar_nticks=5, caps=dict(x_show=False, y_show=False)))fig.show()
高级等值曲面图
# 生成3个numpy数组X, Y, Z = np.mgrid[-5:5:40j, -5:5:40j, -5:5:40j]# 具体值values = X * X * 0.5 + Y * Y + Z * Z * 2fig = go.Figure(data=go.Isosurface(x=X.flatten(), # 3个坐标y=Y.flatten(),z=Z.flatten(),value=values.flatten(), # 数据值isomin=5, # 值的范围isomax=50,surface_fill=0.7, # 表面填充色度caps=dict(x_show=False, y_show=False),slices_z=dict(show=True, locations=[-1, -9,-5]),slices_y=dict(show=True, locations=[1,8]),))fig.show()
X, Y, Z = np.mgrid[-5:5:40j, -5:5:40j, 0:5:20j]values = X * X * 0.5 + Y * Y + Z * Z * 2fig = go.Figure(data=go.Isosurface(x=X.flatten(), # 3个坐标轴和取值y=Y.flatten(),z=Z.flatten(),value=values.flatten(),isomin=30, # 等曲面的取值大小isomax=50,surface=dict(count=3, fill=0.7, pattern='odd'), # pattern取值:'all', 'odd', 'even'caps=dict(x_show=True, y_show=True),))fig.show()