首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用“plot 9”库绘制曲面三维图形

用“plot 9”库绘制曲面三维图形
EN

Stack Overflow用户
提问于 2018-12-10 13:32:33
回答 1查看 1.5K关注 0票数 3

问题:使用python库'plotnine',我们能绘制一个交互式的三维曲面图吗?

备份解释

  1. 我想要做的是,在python环境下,创建一个具有R绘图语法的交互式3D绘图,就像我们在R中使用ggplot2库一样。这是因为我很难记住matplotlib的语法和其他库(如seaborn )。
  2. 交互式3D绘图是指你可以放大、放大、上下滚动等的3D图形。
  3. 似乎只有Java支持的绘图库scuh才能像bokeh那样或巧妙地创建交互式3D图。但是我想用库“plot9”来创建它,因为库支持ggplot类语法,这很容易记住。
  4. 例如,我是否可以用库“plot 9”绘制像下面这样的三维曲面图? 从csv plotly.plotly z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/ master/api_docs/Mt_ Bruno _海拔.csv‘)数据= go.Surface( z=z_data.as_matrix() )布局= go.Layout(标题=’Mt海拔‘,autosize=False,width=500,height=500,margin=dict( l=65,r=50,b=65,( t=90 )图= go.Figure(data=data,layout=layout) py.iplot(图,文件名=‘海拔-三维-表面’)

上面的代码如下所示。

您可以在此链接中查看完整的交互式三维曲面图。

附注:如果我可以绘制一个交互式的三维图形,它不一定是我们应该使用的“plot 9”库。

谢谢你抽出时间阅读这个问题!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-19 14:12:23

这是可能的,如果你愿意扩大一点,并适用警告。最后的代码非常简单,如:

代码语言:javascript
复制
(
    ggplot_3d(mt_bruno_long)
    + aes(x='x', y='y', z='height')
    + geom_polygon_3d(size=0.01)
    + theme_minimal()
)

其结果是:

首先,您需要将数据转换为长格式:

代码语言:javascript
复制
z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv', index_col=0)
z = z_data.values
nrows, ncols = z.shape
x, y = np.linspace(0, 1, nrows), np.linspace(0, 1, ncols)
x, y = np.meshgrid(x, y)
mt_bruno_long = pd.DataFrame({'x': x.flatten(), 'y': y.flatten(), 'height': z.flatten()})

然后,我们需要创建ggplotgeom_polygon的等价物,并了解第三维空间。

由于编写了这个答案,所以代码现在可以在plotnine3d包中使用,所以您可以只需:

代码语言:javascript
复制
from plotnine3d import ggplot_3d, geom_polygon_3d

但为了完整起见,这是(相对地)简单的:

代码语言:javascript
复制
from plotnine import ggplot, geom_polygon
from plotnine.utils import to_rgba, SIZE_FACTOR


class ggplot_3d(ggplot):
    def _create_figure(self):
        figure = plt.figure()
        axs = [plt.axes(projection='3d')]
        
        figure._themeable = {}
        self.figure = figure
        self.axs = axs
        return figure, axs
    
    def _draw_labels(self):
        ax = self.axs[0]
        ax.set_xlabel(self.layout.xlabel(self.labels))
        ax.set_ylabel(self.layout.ylabel(self.labels))
        ax.set_zlabel(self.labels['z'])


class geom_polygon_3d(geom_polygon):
    REQUIRED_AES = {'x', 'y', 'z'}

    @staticmethod
    def draw_group(data, panel_params, coord, ax, **params):
        data = coord.transform(data, panel_params, munch=True)
        data['size'] *= SIZE_FACTOR

        grouper = data.groupby('group', sort=False)
        for i, (group, df) in enumerate(grouper):
            fill = to_rgba(df['fill'], df['alpha'])
            polyc = ax.plot_trisurf(
                df['x'].values,
                df['y'].values,
                df['z'].values,
                facecolors=fill if any(fill) else 'none',
                edgecolors=df['color'] if any(df['color']) else 'none',
                linestyles=df['linetype'],
                linewidths=df['size'],
                zorder=params['zorder'],
                rasterized=params['raster'],
            )
            # workaround for https://github.com/matplotlib/matplotlib/issues/9535
            if len(set(fill)) == 1:
                polyc.set_facecolors(fill[0])

为了交互性,您可以使用您喜欢的任何matplotlib后端,我使用了ipympl (pip install ipympl,然后是jupyter笔记本单元中的%matplotlib widget )。

注意事项如下:

编辑:如果数据集不可用,下面是一个基于matplotlib文档的自包含示例:

代码语言:javascript
复制
import numpy as np

n_radii = 8
n_angles = 36

radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)[..., np.newaxis]

x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())

z = np.sin(-x*y)
df = pd.DataFrame(dict(x=x,y=y,z=z))

(
    ggplot_3d(df)
    + aes(x='x', y='y', z='z')
    + geom_polygon_3d(size=0.01)
    + theme_minimal()
)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53706764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档