Python和Matplotlib:在Jupyter Notebook中进行3D绘图交互

时间:2022-09-10 22:31:09

I use Jupyter Notebook to make analysis of datasets. There are a lot of plots in the notebook, and some of them are 3d plots.

我使用Jupyter Notebook来分析数据集。笔记本中有很多情节,其中一些是3d图。

Python和Matplotlib:在Jupyter Notebook中进行3D绘图交互

I'm wondering if it is possible to make the 3d plot interactive, so I can later play with it in more details?

我想知道是否有可能使3d绘图具有交互性,所以我稍后可以更详细地使用它?

Maybe we can add a button on it? Clicking it can pop out a 3d plot and people can zoom, pan, rotate etc.

也许我们可以在上面添加一个按钮?点击它可以弹出一个3d图,人们可以缩放,平移,旋转等。


My thougths:

1. matplotlib, %qt

This does not fit my case, because I need to continue plot after the 3d plot. %qt will interfere with later plots.

这不适合我的情况,因为我需要在3d情节后继续绘图。 %qt会干扰以后的情节。

2. mpld3

mpld3 is almost ideal in my case, no need to rewrite anything, compatible with matplotlib. However, it only support 2D plot. And I didn't see any plan working on 3D (https://github.com/mpld3/mpld3/issues/223).

mpld3在我的情况下几乎是理想的,不需要重写任何东西,与matplotlib兼容。但是,它只支持2D绘图。我没有看到任何有关3D的计划(https://github.com/mpld3/mpld3/issues/223)。

3. bokeh + visjs

Didn't find any actualy example of 3d plot in bokeh gallery. I only find https://demo.bokehplots.com/apps/surface3d, which uses visjs.

没有在散景库中找到3d绘图的任何实际例子。我只找到使用visjs的https://demo.bokehplots.com/apps/surface3d。

4. Javascript 3D plot?

Since what I need is just line and surce, is it possible to pass the data to js plot using js in the browser to make it interacive? (Then we may need to add 3d axis as well.) This may be similar to visjs, and mpld3.

因为我需要的只是线和外观,是否可以使用浏览器中的js将数据传递给js plot以使其具有交互性? (然后我们可能还需要添加3d轴。)这可能类似于visjs和mpld3。

5 个解决方案

#1


31  

try:

%matplotlib notebook

see jakevdp reply here

看到j​​akevdp在这里回复

EDIT for JupyterLab users:

编辑JupyterLab用户:

Follow the instructions to install jupyter-matplotlib

按照说明安装jupyter-matplotlib

Then the magic command above is no longer needed, as in the example:

然后不再需要上面的魔术命令,如示例中所示:

import ipympl
import matplotlib.pyplot as plt

plt.plot([0, 1, 2, 2])
plt.show()

Finally, note Maarten Breddels' reply; IMHO ipyvolume is indeed very impressive (and useful!).

最后,请注意Maarten Breddels的回复;恕我直言ipyvolume确实非常令人印象深刻(和有用!)。

#2


7  

There is a new library called ipyvolume that may do what you want, the documentation shows live demos. The current version doesn't do meshes and lines, but master from the git repo does (as will version 0.4). (Disclaimer: I'm the author)

有一个名为ipyvolume的新库可以做你想要的,文档显示现场演示。当前版本不做网格和线,但是git repo的master会做(版本0.4)。 (免责声明:我是作者)

#3


2  

For 3-D visualization pythreejs is the best way to go probably in the notebook. It leverages the interactive widget infrastructure of the notebook, so connection between the JS and python is seamless.

对于三维可视化,pythreejs是可能在笔记本中使用的最佳方式。它利用笔记本电脑的交互式小部件基础架构,因此JS和python之间的连接是无缝的。

A more advanced library is bqplot which is a d3-based interactive viz library for the iPython notebook, but it only does 2D

一个更高级的库是bqplot,这是一个基于d3的iPython笔记本的交互式viz库,但它只做2D

#4


2  

Plotly is missing in this list. I've linked the python binding page. It definitively has animated and interative 3D Charts. And since it is Open Source most of that is available offline. Of course it is working with Jupyter

此列表中缺少Plotly。我已经链接了python绑定页面。它最终具有动画和交互式3D图表。由于它是开放源代码,因此大部分内容都可以脱机使用。当然它正在与Jupyter合作

#5


2  

A solution I came up with is to use a vis.js instance in an iframe. This shows an interactive 3D plot inside a notebook, which still works in nbviewer. The visjs code is borrowed from the example code on the 3D graph page

我想出的解决方案是在iframe中使用vis.js实例。这显示了笔记本内部的交互式3D图,它仍然可以在nbviewer中使用。 visjs代码借用于3D图形页面上的示例代码

A small notebook to illustrate this: demo

一个小笔记本来说明这一点:演示

The code itself:

代码本身:

from IPython.core.display import display, HTML
import json

def plot3D(X, Y, Z, height=600, xlabel = "X", ylabel = "Y", zlabel = "Z", initialCamera = None):

    options = {
        "width": "100%",
        "style": "surface",
        "showPerspective": True,
        "showGrid": True,
        "showShadow": False,
        "keepAspectRatio": True,
        "height": str(height) + "px"
    }

    if initialCamera:
        options["cameraPosition"] = initialCamera

    data = [ {"x": X[y,x], "y": Y[y,x], "z": Z[y,x]} for y in range(X.shape[0]) for x in range(X.shape[1]) ]
    visCode = r"""
       <link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css" type="text/css" rel="stylesheet" />
       <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
       <div id="pos" style="top:0px;left:0px;position:absolute;"></div>
       <div id="visualization"></div>
       <script type="text/javascript">
        var data = new vis.DataSet();
        data.add(""" + json.dumps(data) + """);
        var options = """ + json.dumps(options) + """;
        var container = document.getElementById("visualization");
        var graph3d = new vis.Graph3d(container, data, options);
        graph3d.on("cameraPositionChange", function(evt)
        {
            elem = document.getElementById("pos");
            elem.innerHTML = "H: " + evt.horizontal + "<br>V: " + evt.vertical + "<br>D: " + evt.distance;
        });
       </script>
    """
    htmlCode = "<iframe srcdoc='"+visCode+"' width='100%' height='" + str(height) + "px' style='border:0;' scrolling='no'> </iframe>"
    display(HTML(htmlCode))

#1


31  

try:

%matplotlib notebook

see jakevdp reply here

看到j​​akevdp在这里回复

EDIT for JupyterLab users:

编辑JupyterLab用户:

Follow the instructions to install jupyter-matplotlib

按照说明安装jupyter-matplotlib

Then the magic command above is no longer needed, as in the example:

然后不再需要上面的魔术命令,如示例中所示:

import ipympl
import matplotlib.pyplot as plt

plt.plot([0, 1, 2, 2])
plt.show()

Finally, note Maarten Breddels' reply; IMHO ipyvolume is indeed very impressive (and useful!).

最后,请注意Maarten Breddels的回复;恕我直言ipyvolume确实非常令人印象深刻(和有用!)。

#2


7  

There is a new library called ipyvolume that may do what you want, the documentation shows live demos. The current version doesn't do meshes and lines, but master from the git repo does (as will version 0.4). (Disclaimer: I'm the author)

有一个名为ipyvolume的新库可以做你想要的,文档显示现场演示。当前版本不做网格和线,但是git repo的master会做(版本0.4)。 (免责声明:我是作者)

#3


2  

For 3-D visualization pythreejs is the best way to go probably in the notebook. It leverages the interactive widget infrastructure of the notebook, so connection between the JS and python is seamless.

对于三维可视化,pythreejs是可能在笔记本中使用的最佳方式。它利用笔记本电脑的交互式小部件基础架构,因此JS和python之间的连接是无缝的。

A more advanced library is bqplot which is a d3-based interactive viz library for the iPython notebook, but it only does 2D

一个更高级的库是bqplot,这是一个基于d3的iPython笔记本的交互式viz库,但它只做2D

#4


2  

Plotly is missing in this list. I've linked the python binding page. It definitively has animated and interative 3D Charts. And since it is Open Source most of that is available offline. Of course it is working with Jupyter

此列表中缺少Plotly。我已经链接了python绑定页面。它最终具有动画和交互式3D图表。由于它是开放源代码,因此大部分内容都可以脱机使用。当然它正在与Jupyter合作

#5


2  

A solution I came up with is to use a vis.js instance in an iframe. This shows an interactive 3D plot inside a notebook, which still works in nbviewer. The visjs code is borrowed from the example code on the 3D graph page

我想出的解决方案是在iframe中使用vis.js实例。这显示了笔记本内部的交互式3D图,它仍然可以在nbviewer中使用。 visjs代码借用于3D图形页面上的示例代码

A small notebook to illustrate this: demo

一个小笔记本来说明这一点:演示

The code itself:

代码本身:

from IPython.core.display import display, HTML
import json

def plot3D(X, Y, Z, height=600, xlabel = "X", ylabel = "Y", zlabel = "Z", initialCamera = None):

    options = {
        "width": "100%",
        "style": "surface",
        "showPerspective": True,
        "showGrid": True,
        "showShadow": False,
        "keepAspectRatio": True,
        "height": str(height) + "px"
    }

    if initialCamera:
        options["cameraPosition"] = initialCamera

    data = [ {"x": X[y,x], "y": Y[y,x], "z": Z[y,x]} for y in range(X.shape[0]) for x in range(X.shape[1]) ]
    visCode = r"""
       <link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css" type="text/css" rel="stylesheet" />
       <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
       <div id="pos" style="top:0px;left:0px;position:absolute;"></div>
       <div id="visualization"></div>
       <script type="text/javascript">
        var data = new vis.DataSet();
        data.add(""" + json.dumps(data) + """);
        var options = """ + json.dumps(options) + """;
        var container = document.getElementById("visualization");
        var graph3d = new vis.Graph3d(container, data, options);
        graph3d.on("cameraPositionChange", function(evt)
        {
            elem = document.getElementById("pos");
            elem.innerHTML = "H: " + evt.horizontal + "<br>V: " + evt.vertical + "<br>D: " + evt.distance;
        });
       </script>
    """
    htmlCode = "<iframe srcdoc='"+visCode+"' width='100%' height='" + str(height) + "px' style='border:0;' scrolling='no'> </iframe>"
    display(HTML(htmlCode))