簡體   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