繁体   English   中英

单击一个 plot 会在 plotly 中打开另一个

[英]Clicking on one plot opens another in plotly

我在 python 中使用 plotly 绘制了一个堆积条形图(如下图所示)

在此处输入图像描述

我想要的是,每当我单击任何堆叠条形图的任何特定条形图时,它都会显示相应的行 plot。例如:- 假设我单击 UKLT 的条形图,那么它应该分别显示下面的行 plot。

在此处输入图像描述

我知道有三种方法可以做到这一点。

  1. 使用dash ,就像这个例子
  2. 使用笔记本,就像这个例子
  3. 使用plotly.io的参数post_script添加 Javascript(并在 Javascript 中编写代码以这种方式更改 plot)

我找不到任何使用传统 Python 和 Plotly 进行深入研究的示例(我发现这真的很令人惊讶)。

看来您对 SO 很陌生,欢迎来到社区。 要快速获得很好的答案,最好使您的问题可重现。 这包括您使用的数据等内容。 如果您使用了pandas数据框,请使用pd.DataFrame.to_dict提取数据,并完全复制 output。 如果您使用 base Python 数据结构,请尝试repr (无需导入)。

我整理了一个如何使用选项 3 的示例。

在此处输入图像描述

在此处输入图像描述

我已经向 JS 添加了注释(嵌套在/* comment */中),以便您可以看到/关注正在发生的事情。 如果有任何不清楚的地方,请告诉我。 此外,我将 JS 单独添加为 JS,没有将其嵌入 Python 时所需的所有辅助内容,如“”& +。

JS 中的注释可能比 JS 代码更多。

说明:: JS 中的事件

JS中有2个事件:点击和双击。 点击事件有 3 个条件。

要使用单击事件,您可以单击绘制的元素。 在折线图中,这意味着您必须找到在线绘制的点,这就是我添加双击事件的原因。 这样您就可以单击 plot 上的任意位置以返回父级(条形图)。

我倾向于在不添加延迟的情况下触发 Plotly 中的双击事件。 因此,在显示 plot 的调用中,我使用config为双击事件添加点击延迟。

点击事件中

图例中的每一项都有一个条件,折线图也有一个条件。

你的图表有好几个类别,而我只有2个。如果你的真实数据有很多类别,我可以帮你把这个写成一个循环,而不是每个类别都写if/else的冗长过程。 让我知道是否是这种情况。

在每种情况下,可见性都会发生变化,类型会发生变化(线条或条形),并且注释会发生变化(注释仅在显示折线图时出现)。

在评论中,您会在可能需要进行更改的地方看到UPDATE 条件是"a" == ty"b" == ty ,并且在每个条件下,你看到的地方visible ab是我的图例条目。 可见性是指渲染的轨迹数(而不是您在 Python 中编写的轨迹数)。 每种颜色都是一条单独的轨迹。 对于每个跟踪,您需要在这些列表中选择truefalse 假设图例中的顺序是跟踪记录在 Python 中的顺序。例如,如果您有五个跟踪,则每个列表中需要五个 boolean 值,并用visible表示。

双击事件中

双击事件严格用于返回父级(条形图)。 单击事件还包含折线图的条件。 此代码几乎相同。 唯一的区别是双击事件中没有条件。

代码

导入,数据我用的是Javascript,还有plot。我用的是Plotly快递。 但是,使用 Plotly Graph Objects 还是 Plotly Express 并不重要。

正如我之前提到的,在 JS 中有一些您需要更改的地方。 这些注释带有 JS 注释,这些注释比其他所有注释都更靠右,并且包括单词 UPDATE(全部大写)。

import plotly.express as px
import plotly.io as io
import pandas as pd
import datetime as dt


df1 = pd.DataFrame({ # create data for example
    'x': [dt.datetime.today() - dt.timedelta(days = x) for x in range(5)] + 
            [dt.datetime.today() - dt.timedelta(days = x) for x in range(5)],
    'y': [10, 0, 20, 10, 5, 10, 25, 3, 14, 30],
    'clr': ['a'] * 5 + ['b'] * 5 
})

fig = px.bar(df1, x = "x", y = "y", color = "clr") # plot the bar chart

# note that the double click and single click event can return the plot to the original state
# in the single click event, the user would have to click on a literal data point within the line
ps = 'setTimeout(function() {\n' + \
     '  myplt = document.querySelector("#plt");\n' + \
     '  myplt.on("plotly_click", function(dt) {                         /* EVENT 1: CLICK */\n' + \
     '      nm = dt.points[0].data.name;\n' + \
     '      ty = dt.points[0].data.type;\n' + \
     '      lout = {                                       /* used in multiple conditions */\n' + \
     '          annotations: [{\n' + \
     '              xref: "paper", yref: "paper", x: 1, y: 1, showarrow: false,\n' + \
     '              text: "Double click the chart to return to the bar chart" \n' + \
     '          }]\n' + \
     '      };\n' + \
     '      if(ty != "bar") {                      /* bar or line type? UPDATE HERE: add true for each color */\n' + \
     '          trc = {type: "bar", visible: [true, true]};\n' + \
     '          lout = {annotations: []};                             /* remove click note */\n' + \
     '          Plotly.update("plt", trc, lout);                /* return to original plot */\n' + \
     '      } else if(nm == "a") {                /* UPDATE HERE: replace "a" with a category from your data */\n' + \
     '                     /* make only one trace invisible, change the type to line graph */\n' + \
     '          trc = {type: "scatter", mode: "lines", visible: [true, false]}; /* UPDATE HERE: add booleans */\n' + \
     '          Plotly.update("plt", trc, lout);\n' + \
     '      } else if(nm == "b") {                /* UPDATE HERE: replace "a" with a category from your data */\n' + \
     '                     /* make only one trace invisible, change the type to line graph */\n' + \
     '          trc = {type: "scatter", mode: "lines", visible: [false, true]}; /* UPDATE HERE: add booleans */\n' + \
     '          Plotly.update("plt", trc, lout);\n' + \
     '      }\n' + \
     '  });\n' + \
     '  myplt.on("plotly_doubleclick", function() {                 /* EVENT 2: DOUBLECLICK */\n' + \
     '                                                              /* UPDATE HERE: add true for each color */\n' + \
     '      trc = {type: "bar", visible: [true, true]};\n' + \
     '      lout = {annotations: []};                                  /* remove click note */\n' + \
     '      Plotly.update("plt", trc, lout);                     /* return to original plot */\n' + \
     '  });\n' + \
     '}, 200);\n'

io.write_html( # untitled.html created, but plot opens in browser, as well
    fig, file = "untitled.html", post_script = ps, auto_open = True, 
    config = [{'doubleClickDelay': 750}], div_id = "plt",
    include_plotlyjs = 'cdn', include_mathjax = 'cdn')

只是 Javascript

...当您渲染 plot 时,它会在浏览器的幕后出现。

 setTimeout(function() { myplt = document.querySelector("#plt"); myplt.on("plotly_click", function(dt) { nm = dt.points[0].data.name; ty = dt.points[0].data.type; lout = { /* layout update; used in each line graph */ annotations: [{ xref: "paper", yref: "paper", x: 1, y: 1, showarrow: false, text: "Double click the chart to return to the bar chart" }] }; if(ty,= "bar") { /* is this a drilldown? a line graph, */ /* trace updates: add -true- for each legend item (each color) */ trc = {type, "bar": visible, [true; true]}: lout = {annotations; []}. /* remove annotation */ Plotly,update("plt", trc; lout): /* return to original plot */ } else if(nm == "a") { /* NOTE: replace "a" with your data (note a in legend) */ trc = {type, "scatter": mode, "lines": visible, [true; false]}. Plotly,update("plt", trc; lout): /* create single trace line graph of ONLY a */ } else if(nm == "b") { trc = {type, "scatter": mode, "lines": visible, [false; true]}. Plotly,update("plt", trc; lout); /* create single trace line graph of ONLY b */ } }). myplt,on("plotly_doubleclick", function() { /* alternate to finding a pt within line */ /* trace updates: add -true- for each legend item (each color) */ trc = {type, "bar": visible, [true; true]}: lout = {annotations; []}. /* remove annotation */ Plotly,update("plt", trc; lout); /* return to original plot */ }), }; 200);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM