Поместите диаграмму в всплывающее окно

Я использую plotly для R, хотя я открыт для использования версии Python. Когда я наматываюсь на datapoint, есть ли способ заставить всплывающее окно содержать другой график? В идеале диаграмма будет создана из данных, хотя я могу использовать статическое изображение в качестве резервной копии.

Я не знаю, с чего начать, и заранее извиняюсь за отсутствие MWE.

3 Solutions collect form web for “Поместите диаграмму в всплывающее окно”

Решение 1: Придерживайтесь R

Благодаря @MLavoie. В следующем примере используйте чистый R чтобы создать два графика: «mainplot» и «hover», которые реагируют на событие наведения первого.

 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 . Для каждого события hover на сервер отправляется запрос POST , после чего сервер обновляет всплывающее окно. Это очень неэффективно, поэтому может плохо работать на медленных соединениях.

Вышеприведенный код предназначен только для демонстрации и еще не проверен. См. Рабочий и более сложный пример здесь (с источником ).

Решение 2: Javascript

Да, вы можете это сделать, используя API Javascript .

Короткий ответ

  1. Создайте свой график, используя R или Python или любой другой поддерживаемый язык.
  2. Вставьте график в новую HTML-страницу и добавьте функцию обратного вызова, как показано в примере ниже. Если у вас есть хорошие знания о DOM , вы также можете добавить JS в исходный HTML вместо создания нового.
  3. Нарисуйте всплывающий график внутри функции обратного вызова, который принимает параметры, содержащие данные дататанта на ходу.

Детали

Как упоминалось в @MLavoie, хороший пример показан в plotly.hover-events

Давайте копаем код. В JS-файле есть функция обратного вызова, связанная с 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 на странице примера. Он имеет такую ​​структуру:

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

Рабочий пример:

Для демонстрации я подготовлю простой пример здесь (нажмите, чтобы попробовать):

 <!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> 

Это изменено из примера poltly.hover-events для python. Вместо того, чтобы всплывать изображение, я onhover обратный вызов onhover для построения кривой, основанной на значении y каждого бара.

Основная диаграмма генерируется python и вставляется здесь как iframe . Вы можете сделать свой собственный на любом языке, включая R На этой странице мы добавляем <div id="myDiv"></div> и используем plotly.js для рисования всплывающей диаграммы.

Экспорт данных R в среду JS

Shiny использует jsonlite для преобразования R объектов в json и отправки их клиенту. Мы можем использовать тот же механизм для упаковки и отправки нашего фрейма данных, чтобы обратный вызов JS мог использовать данные для отображения всплывающей диаграммы.

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.

Более подробно идет здесь и здесь .

Если вы хотите придерживаться R вы можете использовать Shiny чтобы получить почти тот результат, который вы хотите. При наведении каждой точки изображение будет отображаться под основным графиком. В приведенном ниже примере я использовал первые три строки mtcars данных mtcars . Для запуска кода вам понадобится только 3 логотипа / изображения, соответствующие имени первых трех строк (в этом mtcars$name , Mazda RX4 , Mazda RX4 Wag , Datsun 710 ).

  library(shiny) library(plotly) datatest <- diamonds %>% count(cut) datatest$ImageNumber <- c(0, 1, 2, 3, 4) datatest$name <- c("Image0", "Image1", "Image2", "Image3", "Image4") ui <- fluidPage( plotlyOutput("plot"), # verbatimTextOutput("hover2"), #imageOutput("hover"), plotlyOutput("hover3") ) server <- function(input, output, session) { output$plot <- renderPlotly({ plot_ly(datatest, x = cut, y = n, type = "bar", marker = list(color = toRGB("black"))) }) selected_image <- reactive({ eventdat <- event_data('plotly_hover', source = 'A') ImagePick <- as.numeric(eventdat[['pointNumber']]) sub <- datatest[datatest$ImageNumber %in% ImagePick, ] return(sub) }) # output$hover2 <- renderPrint({ #d <- event_data("plotly_hover") #if (is.null(d)) "Hover events appear here (unhover to clear)" else d #}) # output$hover <- renderImage({ # datag <- selected_image() #filename <- normalizePath(file.path('/Users/drisk/Desktop/temp', # paste(datag$name, '.png', sep=''))) # Return a list containing the filename and alt text # list(src = filename, # alt = paste("Image number", datag$name)) # }, deleteFile = FALSE) output$hover3 <- renderPlotly({ datag <- selected_image() # draw plot according to the point number on hover plot_ly(data=datag, x = ImageNumber, y = n, mode = "scatter") }) } shinyApp(ui, server) 

введите описание изображения здесь

Кажется, что ответы, которые вы опубликовали, не работают для вас @Adam_G. Я изучал похожие библиотеки для своей собственной работы и решил, что Plot.ly не всегда является правильным путем, когда вы хотите использовать расширенные функции. Вы видели bokeh ? Он в основном разработан для этого типа задач и намного проще реализовать (также библиотека Plot.ly такая как Plot.ly ). Вот копия приведенного им примера, в котором вы можете перемещать ползунок, чтобы изменить график данных (аналогично примеру, опубликованному @gdlmx для Plot.ly, но вы можете использовать его, не размещая его на веб-сайте). Я добавил пакет flexx , чтобы вы могли использовать это пишущий чистый Python (без JavaScript – он может переводить функции Python на JavaScript ( CustomJS.from_py_func(callback) ) https://github.com/zoofIO/flexx-notebooks/blob/master/ flexx_tutorial_pyscript.ipynb ):

 from bokeh.io import vform from bokeh.models import CustomJS, ColumnDataSource, Slider from bokeh.plotting import figure, output_file, show import flexx output_file("callback.html") x = [x*0.005 for x in range(0, 200)] y = x source = ColumnDataSource(data=dict(x=x, y=y)) plot = figure(plot_width=400, plot_height=400) plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6) def callback(source=source): data = source.get('data') f = cb_obj.get('value') #this is the bokeh callback object, linked to the slider below x, y = data['x'], data['y'] for i in range(len(x)): y[i] = x[i]**f #the slider value passed to this function as f will alter chart as a function of x and y source.trigger('change') #as the slider moves, the chart will change slider = Slider(start=0.1, end=4, value=1, step=.1, title="power", callback=CustomJS.from_py_func(callback)) layout = vform(slider, plot) show(layout) 

См. Здесь фактический пример в действии: http://bokeh.pydata.org/en/0.10.0/docs/user_guide/interaction.html#customjs-for-widgets

Чтобы интегрироваться с событиями зависания, см. Здесь ( from bokeh.models import HoverTool ): http://bokeh.pydata.org/en/0.10.0/docs/user_guide/interaction.html#customjs-for-hover

Пример наведения:

 from bokeh.plotting import figure, output_file, show, ColumnDataSource from bokeh.models import HoverTool output_file("toolbar.html") source = ColumnDataSource( data=dict( x=[1, 2, 3, 4, 5], y=[2, 5, 8, 2, 7], desc=['A', 'b', 'C', 'd', 'E'], ) ) hover = HoverTool( tooltips=[ ("index", "$index"), ("(x,y)", "($x, $y)"), ("desc", "@desc"), ] ) p = figure(plot_width=400, plot_height=400, tools=[hover], title="Mouse over the dots") p.circle('x', 'y', size=20, source=source) show(p) 

Глядя на 1-й код, вы можете поместить любую формулу, которая вам нужна, в def callback – некоторые из них требуются. Вы можете получить зависание, чтобы изменить график рядом с ним ( hform(leftchart, rightchart) или выше / ниже него ( vform(topchart, bottomchart) ). Это передается как CustomJS который bokeh использует для обеспечения возможности расширения, и flexx позволяет писать это в Python.

Альтернативой является установка того, что вы хотите настроить на tooltips с помощью HTML (хотя в этом примере размещаются изображения в словарях вместо новых графиков из базовых данных): http://bokeh.pydata.org/en/0.10.0/ документы / user_guide / tools.html # заказа подсказка

  • Почему SciPy возвращает отрицательные p-значения для чрезвычайно малых значений p с точным тестом Fisher?
  • Есть ли в Python модуль, который делает что-то вроде «sqldf» для R?
  • Реализация Python теста перестановки с номером перестановки в качестве входного
  • эквивалент python qnorm, qf и qchi2 из R
  • Как удалить повторяющиеся элементы в векторе, аналогично 'set' в Python
  • Создание порогового кода ROC в Python
  • Создание коррелированных данных в Python (3.3)
  • Выполнение R-кода на `python` с помощью SyntaxError: ключевое слово не может быть выражением error Message
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.