可能控制一个阴谋图在木星从markdown链接?



我想用Plotly,在木星上画一个相当简单的线形图,像这样:

import plotly.graph_objs as go
from plotly.subplots import make_subplots
figSubs = go.FigureWidget(
make_subplots(rows=2, cols=1, specs = [[{}], [{}]], vertical_spacing = 0.05)
)
figSubs.add_trace(
go.Scatter(mode='lines+markers', x=[0, 1, 2, 3, 4], y=[0, 1000, 990, 980, 970], name='Test', marker={'color': 'red'}, xaxis="x1"),
row=1, col=1
)
figSubs.update_layout(margin=go.layout.Margin(l=20,t=10,b=10,pad=4))

我找到了https://towardsdatascience.com/interactive-visualization-of-decision-trees-with-jupyter-widgets-ca15dd312084,它使用from ipywidgets import interactive来获得交互式小部件,可以控制Plotly情节。

然而,我想要的是,有Markdown链接,改变Plotly图。更具体地说,我想改变范围-如果我们按照Plotly:如何设置y轴的范围?或如何强迫情节。如何使用给定的y轴范围?,我想有这样的链接:

  • [click here for yrange of 0-1000](???)将执行figSubs['layout']['yaxis1'].update(range=[0, 1000], autorange=False)
  • [click here for yrange of 950-1000](???)将执行figSubs['layout']['yaxis1'].update(range=[950, 1000], autorange=False)

在Jupyter笔记本中,大多数Plotly设置代码是Python的,这样的事情可能吗?

嗯,显然,这是可能的-但是男孩,这是困难得到所有这些信息到位,以便得到一个工作的例子…

首先,这些是我已经安装的版本:

$ python3 --version
Python 3.8.10
$ pip3 list | grep 'jupyter |nbextensions|plotly'
jupyter                           1.0.0
jupyter-contrib-nbextensions      0.5.1
jupyter-nbextensions-configurator 0.4.1
plotly                            5.2.2

和一些要点:

  • 虽然,原则上,它可能可以在Markdown链接中使用到javascript的链接-在实践中,它不是:Jupyter Markdown单元格链接是消毒的,特别是如果它们使用冒号,没有href传播给它们(也尝试过urlencoding那里,它没有工作)。
    • 这意味着,唯一的解决方案是将您的Jupyter单元定义为Code(在本例中是IPython内核),然后使用"magic";命令%%html,以便能够逐字输出HTML和JavaScript
  • 这里的主要技巧是使用Jupyter.notebook.kernel.executeJavaScript函数,从JavaScript调用内核(这里是IPython)代码;但是,请注意文档IPython.notebook.kernel.execute函数·Issue #2219·jupyter/notebook有点缺乏;
    • 我得到了正确的使用示例(JavaScriptPromiseiopub回调)通过如何正确使用内核。执行方法的Jupyter笔记本在Javascript(时间问题)?·jupyter/notebook和IPython notebook ~使用javascript运行python代码?→要点:在Jupyter笔记本
    • 中从JavaScript运行Python代码
  • 使用这种方法,每当您使用figure.show()pio.show(figure)方法时,JavaScript/Python连接中的某些东西将中断,并且图形将无法更新-即使否则,代码似乎运行(如console.log跟踪所证明);在这种情况下唯一有效的函数是display(figure)

注意在这个例子中:

  • 有一个plot/IPython交互下拉菜单,它独立地改变plot
  • 的范围
  • 有一个Python函数来调整范围,这里它被从Python和JavaScript调用(链接)

话虽如此,这里应该是一个工作示例;在第一个单元格中,使用生成图形的Python代码(因此,定义为代码单元格):


import plotly.graph_objs as go
import pandas as pd
from plotly.subplots import make_subplots
# import plotly.io as pio # https://plotly.com/python/getting-started-with-chart-studio/
from IPython.display import display, HTML
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/volcano.csv")
figSubs = go.FigureWidget(
make_subplots(rows=2, cols=1, specs = [[{}], [{}]], vertical_spacing = 0.05)
)
figSubs.add_trace(
go.Scatter(mode='lines+markers', x=df["V1"], y=df["V55"], name='Test1', marker={'color': 'red'}, xaxis="x1"),
row=1, col=1
)
figSubs.add_trace(
go.Scatter(mode='lines+markers', x=[0, 1, 2, 3, 4], y=[0, 990, 980, 970, 960], name='Test21', marker={'color': 'blue'}, xaxis="x1"),
row=2, col=1
)
figSubs.add_trace(
go.Scatter(mode='lines+markers', x=[0, 1, 2, 3, 4], y=[0, 980, 970, 960, 950], name='Test22', marker={'color': 'violet'}, xaxis="x1"),
row=2, col=1
)
figSubs.update_layout(margin=go.layout.Margin(l=20,t=10,b=10,pad=4))
figSubs.update_yaxes(zeroline=True,showline=True,zerolinewidth=1,zerolinecolor="#000", row=1, col=1)
figSubs.update_yaxes(zeroline=True,showline=True,zerolinewidth=1,zerolinecolor="#000", row=2, col=1)
# Add dropdown
figSubs.update_layout(
updatemenus=[
dict(
buttons=list([
dict(
args=[{"yaxis.range": [0, 1000], "yaxis.autorange": False, "row": 1, "col": 1}],
label="[0, 1000]",
method="relayout"
),
dict(
args=[{"yaxis.range": [100, 200], "yaxis.autorange": False}],
label="[100, 200]",
method="relayout"
)
]),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=0.1,
xanchor="left",
y=1.12,
yanchor="top"
),
]
)
# the Python function to adjust the Y range of the first plot - which is also called from JavaScript
def PsetMyYRange(ymin, ymax, dodraw=True):
figSubs['layout']['yaxis'].update(range=[ymin, ymax], autorange=False)
#figSubs.update_yaxes(range=[ymin, ymax]) # changes both!
#figSubs.update_layout(margin=go.layout.Margin(l=200,t=100,b=100,pad=40))
#figSubs.show() # do NOT call this, else cannot manupulate the plot via JavaScript calls of this function later on!
if dodraw:
display(figSubs) #MUST have this to update the plot from JavaScript->Python; note with Plotly in a Jupyter extension, there is no `Plotly` javascript object accessible on the page! 
return "{}; {}; {}".format(figSubs, ymin, ymax) # just for the console.log printout
PsetMyYRange(110,120,dodraw=False) # call once to make sure it also works from here; but don't "draw", else we get two plots
#figSubs.show()    # NOTE: .show() at end, will prevent the PsetMyYRange being able to redraw!
#pio.show(figSubs) # NOTE: also pio.show() at end, will prevent the PsetMyYRange being able to redraw!
display(figSubs)   # ... display() works fine however

第二个单元格,应该是"降价链接";单元格,如OP中所希望的那样,同样必须是Code单元格,使用%%html魔术命令:

%%html
<script type='text/javascript'>
window.executePython = function(python) {
return new Promise((resolve, reject) => {
var callbacks = {
iopub: {
output: (data) => resolve(data.content.text.trim())
}
};
Jupyter.notebook.kernel.execute(`print(${python})`, callbacks);    
});
}
function setMyYRange(ymin, ymax){
// NONE of the below quite works - we must call via Promise:
//objstring = IPython.notebook.kernel.execute("global figSubs; print(figSubs)");
//prevstring = IPython.notebook.kernel.execute("print(Jupyter.notebook.get_prev_cell())");
//runstring = "global figSubs; figSubs['layout']['yaxis'].update(range=["+ymin+", "+ymax+"], autorange=False)";
//console.log("setMyYRange " + ymin + " " + ymax + " ... " + objstring + " ... " + prevstring + " ... " + runstring);
//IPython.notebook.kernel.execute(runstring);
// the only thing needed for the code to work:
window.executePython("PsetMyYRange("+ymin+","+ymax+")")
.then(result => console.log(result));
}
</script>
<a onclick="javascript:setMyYRange(0,1000);" href="javascript:void(0);">here (0,1000)</a>
<a onclick="javascript:setMyYRange(100,200);" href="javascript:void(0);">here (100,200)</a>

相关内容

  • 没有找到相关文章

最新更新