将图表放置在可绘制的弹出窗口中 [英] Place a chart in plotly popup

查看:84
本文介绍了将图表放置在可绘制的弹出窗口中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管我也愿意使用Python版本,但我正在为R使用plotly.当我将鼠标悬停在数据点上时,是否有办法使弹出窗口包含另一个图表?理想情况下,图表可以根据数据创建,尽管我可以使用静态图片作为后备广告.

I'm using plotly for R, although I'm open to using the Python version, as well. When I hover over a datapoint, is there a way to make the popup contain another chart? Ideally the chart would be created from the data, although I can use a static image as a fallback.

我不确定从哪里开始,并为没有MWE提前道歉.

I'm unsure where to start on this, and apologize in advance for not having an MWE.

推荐答案

解决方案1:坚持使用R

感谢@MLavoie.下面的示例使用纯R来创建两个图,"mainplot"和"hover"对第一个图的悬停事件做出反应.

Solution 1: Stick to R

Thanks to @MLavoie. The following example use pure R to create two plot, the "mainplot" and the "hover" which reacts to the hover event of the first one.

library(shiny)
library(plotly)

ui <- fluidPage(
  plotlyOutput("mainplot"),
  plotlyOutput("hover")
)

server <- function(input, output) {
  output$mainplot <- renderPlotly({
    # https://plot.ly/r/
    d <- diamonds[sample(nrow(diamonds), 1000), ]
    plot_ly(d, x = carat, y = price, text = paste("Clarity: ", clarity), mode = "markers", color = carat, size = carat, source="main")
  })

  output$hover <- renderPlotly({
    eventdat <- event_data('plotly_hover', source="main") # get event data from source main
    if(is.null(eventdat) == T) return(NULL)        # If NULL dont do anything
    point <- as.numeric(eventdat[['pointNumber']]) # Index of the data point being charted

    # draw plot according to the point number on hover
    plot_ly(  x = c(1,2,3), y = c(point, point*2, point*3), mode = "scatter")
  })
}
shinyApp(ui, server)

此示例使用 shiny binds for plotly . 对于每个悬停事件,都会向服务器发送POST请求,然后服务器将更新弹出式图表.它的效率很低,因此在连接速度较慢的情况下可能无法很好地工作.

This example use the shiny binds for plotly. For every hover event, a POST request is sent to the server, then the server will update the popup-chart. It's very inefficient thus may not work well on slow connections.

以上代码仅用于演示,尚未经过测试.在此处(使用

The above code is just for demo, and not yet tested. See a working and much more complicated example here (with source).

是的,您可以使用 plotly Javascript API 完成.

Yes, you can do it using the plotly Javascript API.

  1. 使用RPython或任何其他受支持的语言创建图形.
  2. 将图形插入新的HTML页面,并添加一个回调函数,如下例所示.如果您对 DOM 有足够的了解,还可以将JS添加到原始HTML而不是创建一个新的.
  3. 在回调函数内部绘制弹出图,该函数接受包含悬停数据点数据的参数.
  1. Create your graph using R or Python or any other supported language.
  2. Insert the graph into a new HTML page and add a callback function as shown in the example below. If you have good knowledge about DOM, you can also add the JS to the original HTML instead of creating a new one.
  3. Draw the popup graph inside the callback function which accepts parameters containing the data of the datapoint on-hover.

详细信息

如@MLavoie所述, plotly.hover-events 中显示了一个很好的例子.

Details

As @MLavoie mentioned, a good example is shown in plotly.hover-events

让我们深入研究代码.在JS文件中,Plot附加了一个简单的回调函数:

Let's dig into the code. In the JS file, there is a simple callback function attached to Plot:

Plot.onHover = function(message) {
var artist = message.points[0].x.toLowerCase().replace(/ /g, '-');

var imgSrc = blankImg;
if(artistToUrl[artist] !== undefined) imgSrc = artistToUrl[artist];

Plot.hoverImg.src = imgSrc;
};

上面,artistToUrl是一个巨大的对象,里面充满了base64字符串,我不会在此处粘贴它来溢出帖子.但是您可以在示例页面的JS标签下看到它.它具有这样的结构:

Above, artistToUrl is a huge object filled with base64 string which I will not paste here to overflow the post. But you can see it under the JS tab of the example page. It has such structure:

var artistToUrl = { 'bob-dylan': 'data:image/jpeg;base64,/...',...}

工作示例:

为进行演示,我准备一个简单的示例此处(点击尝试):

Working example:

For demonstration, I prepare a simple example here (click to try):

<!DOCTYPE html>
<html>
<head>
   <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<iframe id="plot" style="width: 900px; height: 600px;" src="https://plot.ly/~jackp/10816.embed" seamless></iframe>
<div id="myDiv"></div>
<script>
(function main() {
var Plot = { id: 'plot', domain: 'https://plot.ly' };
Plot.onHover = function(message) {
    var y = message.points[0].y; /*** y value of the data point(bar) under hover ***/
    var line1 = {
      x: [0.25,0.5,1],           /*** dummy x array in popup-chart ***/
      y: [1/y, 2, y],            /*** dummy y array in popup-chart ***/
      mode: 'lines+markers'
    };
    var layout = {
      title:'Popup graph on hover',
      height: 400,
      width: 480
    };
    Plotly.newPlot('myDiv', [  line1 ], layout); // this finally draws your popup-chart
};
Plot.init = function init() {
    var pinger = setInterval(function() {
        Plot.post({task: 'ping'});
    }, 500);

    function messageListener(e) {
        var message = e.data;
        if(message.pong) {
            console.log('Initial pong, frame is ready to receive');
            clearInterval(pinger);
            Plot.post({
                'task': 'listen',
                'events': ['hover']
            });
        }
        else if(message.type === 'hover') {
            Plot.onHover(message);
        }
    }
    window.removeEventListener('message', messageListener);
    window.addEventListener('message', messageListener);
};
Plot.post = function post(o) {
    document.getElementById(Plot.id).contentWindow.postMessage(o, Plot.domain);
};

Plot.init();
})();
</script>
</body>
</html>

这是从python的 poltly.hover-events 示例中修改的.我没有弹出图像,而是更改了onhover回调以根据每个条的y值绘制曲线.

This is modified from the poltly.hover-events example for python. Instead of poping up an image, I change the onhover callback to plot a curve based on the y value of the each bar.

主图表由python生成,并在此处插入为iframe.您可以使用任何语言制作自己的语言,包括R.在此页面中,我们添加一个<div id="myDiv"></div>并使用plotly.js在其中绘制弹出图.

The main chart is generated by python and inserted here as iframe. You can make your own by any language including R. In this page we add a <div id="myDiv"></div> and use the plotly.js to draw the popup-chart whithin it.

Shiny使用 jsonlite 进行转换R对象到json,并将它们发送给客户端.我们可以使用相同的机制来打包和发送数据框,以便JS回调可以使用数据来呈现弹出式图表.

Shiny uses jsonlite to convert R objects to json and send them to the client. We can use the same mechanism to pack and send our data frame so that the JS callback can use the data to render the popup chart.

server.r

output$json <- reactive({
  paste('<script>data =', RJSONIO::toJSON(your_data_frame, byrow=T, colNames=T),'</script>')

ui.r

fluidPage(..., htmlOutput("json"), ...)

在JS回调函数中,您可以将data用作任何其他JS对象.

In the JS callback function, you can use data as any other JS objects.

更多详细信息在此处此处.

这篇关于将图表放置在可绘制的弹出窗口中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆