我想使用Tablesaw内核将IJava交互式图形嵌入Jupyter Notebook中。我意识到Tablesaw可能无法做到这一点,但我愿意付出一点努力来实现这一目标。我是Java专家,但是我不熟悉Jupyter Notebook和IJava内核,所以我不确定从哪里开始。是否有一些用于Jupyter Notebook或IJava的用于嵌入对象的API?

首先,我安装了Anaconda,然后毫无问题地在Jupyter Notebook中安装了IJava内核。到目前为止,在Windows 10上使用OpenJDK 11都可以顺利进行!接下来,我尝试使用Tablesaw。我能够添加其Maven依赖项,加载CSV文件并创建图。非常好!

但是,要生成图形,Tablesaw将使用Plotly生成一个临时HTML文件,并调用浏览器以显示交互式图。换句话说,该图形不会出现在Jupyter Notebook内部。

Tablesaw具有一个使用example with embedded graphs内核(不是IJava)的BeakerX,并且您可以看到(向下滚动到“使用线性回归玩(钱)球”),他们将Tablesaw Plot直接嵌入Jupyter Notebook中。因此,我知道可以在概念上将交互式Tablesaw图嵌入到具有Java内核的Jupyter Notebook中。

此功能是BeakerX特有的吗?我将切换到BeakerX,但是从文档中我看不到任何有关BeakerX支持Java 9+的信息。另外,IJava似乎是一种更精简的实现,直接在JShell之上构建。

我从哪里开始弄清楚如何使用IJava内核将Tablesaw Plot对象作为交互式图形嵌入Jupyter Notebook中,以及它们在BeakerX中的工作方式?

最佳答案

IJava内核具有display_data的2个主要功能; displayrender。两者都从base kernel挂接到Renderer中。我们可以在tableaw中为Figure类型注册一个渲染函数。

  • 通过loadFromPOM单元魔术添加了tableaw-jsplot依赖关系(以及所有必需的传递依赖关系):

    %%loadFromPOM
    <dependency>
        <groupId>tech.tablesaw</groupId>
        <artifactId>tablesaw-jsplot</artifactId>
        <version>0.30.4</version>
    </dependency>
    
  • IJava的渲染器注册一个渲染函数。
  • 我们为tech.tablesaw.plotly.components.Figure创建一个注册。
  • 如果在渲染过程中未指定输出类型,则我们希望其默认为text/html(通过preferring调用)。
  • 如果请求html渲染,我们将构建目标<div>以及将plotly渲染调用到<div>中的javascript。这种逻辑的大部分是通过tableaw的asJavascript方法完成的,但是与Jupyter笔记本的require AMD模块设置挂钩。

  • import io.github.spencerpark.ijava.IJava;
    
    IJava.getKernelInstance().getRenderer()
        .createRegistration(tech.tablesaw.plotly.components.Figure.class)
        .preferring(io.github.spencerpark.jupyter.kernel.display.mime.MIMEType.TEXT_HTML)
        .register((figure, ctx) -> {
            ctx.renderIfRequested(io.github.spencerpark.jupyter.kernel.display.mime.MIMEType.TEXT_HTML, () -> {
                String id = UUID.randomUUID().toString().replace("-", "");
    
                figure.asJavascript(id);
                Map<String, Object> context = figure.getContext();
    
                StringBuilder html = new StringBuilder();
                html.append("<div id=\"").append(id).append("\"></div>\n");
                html.append("<script>require(['https://cdn.plot.ly/plotly-1.44.4.min.js'], Plotly => {\n");
                html.append("var target_").append(id).append(" = document.getElementById('").append(id).append("');\n");
                html.append(context.get("figure")).append('\n');
                html.append(context.get("plotFunction")).append('\n');
                html.append("})</script>\n");
                return html.toString();
            });
        });
    
  • 然后,我们可以创建一个要显示的表(取自Tablesaw docs)。

    import tech.tablesaw.api.*;
    import tech.tablesaw.plotly.api.*;
    import tech.tablesaw.plotly.components.*;
    
    String[] animals = {"bear", "cat", "giraffe"};
    double[] cuteness = {90.1, 84.3, 99.7};
    
    Table cuteAnimals = Table.create("Cute Animals")
        .addColumns(
            StringColumn.create("Animal types", animals),
            DoubleColumn.create("rating", cuteness)
        );
    cuteAnimals
    
  • 最后,我们可以为表创建一个Figure并通过3种在IJava中显示事物的方法之一来显示它。

    VerticalBarPlot.create("Cute animals", cuteAnimals, "Animal types", "rating");
    

    这等效于render调用,其中"text/html"是隐式的,因为我们将其设置为首选类型(注册期间的preferring)

    render(VerticalBarPlot.create("Cute animals", cuteAnimals, "Animal types", "rating"), "text/html");
    

    如果它不在单元格的末尾,则display函数是另一个选项。例如,随后显示图表和cuteAnimals:

    Figure figure = VerticalBarPlot.create("Cute animals", cuteAnimals, "Animal types", "rating");
    display(figure);
    
    cuteAnimals
    
  • 09-28 00:14