【问题标题】:Shiny update the clicked point to highlight it闪亮更新点击的点以突出显示它
【发布时间】:2017-08-30 19:39:51
【问题描述】:

这是一个提取点击事件的工作示例。我想问你是否有办法通过增加大小或突出显示等来更新点击的点?

library(shiny)
library(plotly)

ui <- fluidPage(
    plotlyOutput("plot"),
    verbatimTextOutput("click")
)

server <- function(input, output, session) {

    nms <- row.names(mtcars)

    output$plot <- renderPlotly({
        p <- ggplot(mtcars, aes(x = mpg, y = wt, col = as.factor(cyl), key = nms)) + 
           geom_point()
        ggplotly(p)

    })

    output$click <- renderPrint({
        d <- event_data("plotly_click")
        if (is.null(d)) "Click events appear here (double-click to clear)" 
        else cat("Selected point associated with Car: ", d$key)
    })

}

shinyApp(ui, server)

我已经搜索了 SO 和其他适当的来源以找到以下问题的解决方案,但找不到。

更新:

  • This 解决方案更适合这个玩具情节。但是,我的原始用例包含 50 多个级别的感兴趣变量,并且很有可能已经存在洋红色或任何其他颜色。此外,更改颜色需要相当长的时间。
  • 有什么方法可以增加点击点的大小以将其与附近的 100 个点区分开来?

已向here提出了更改点击点形状的相关问题。

【问题讨论】:

  • 有一个可能相关的问题 (dynamic ggplot layers in shiny with nearPoints()) 不涉及plotly
  • @Uwe 谢谢,我会调查的。一个主要观察结果是nearPoints()ggplotly 地块的情况下不起作用。其次,随着整个图再次绘制,可能认为因子水平将获得新的颜色,并且难以从整个图中识别所选区域。

标签: r shiny plotly ropensci ggplotly


【解决方案1】:

您可以使用htmlwidgetonrender 函数将Plotlyevents 添加到您的Shiny 应用程序中。

ggplotly(p) %>% onRender(javascript)

colors 的数组被传递给restyle 函数。选定点 (pointNumber) 为洋红色,而其他点则从图例中获取颜色。你可以用marker 大小做同样的事情,标记符号有点棘手,因为Plotly 在这里不接受数组。

function(el, x){
  el.on('plotly_click', function(data) {
    colors = [];
    var base_color = document.getElementsByClassName('legendpoints')[data.points[0].curveNumber].getElementsByTagName('path')[0].style['stroke']
    for (var i = 0; i < data.points[0].data.x.length; i += 1) {
      colors.push(base_color)
    };
    colors[data.points[0].pointNumber] = '#FF00FF';
    Plotly.restyle(el, 
                   {'marker':{color: colors}}, 
                   [data.points[0].curveNumber]
                  );

  });
}

library(shiny)
library(plotly)
library(htmlwidgets)

ui <- fluidPage(
  plotlyOutput("plot")
)

javascript <- "
function(el, x){
  el.on('plotly_click', function(data) {
    colors = [];

    var base_color = document.getElementsByClassName('legendpoints')[data.points[0].curveNumber].getElementsByTagName('path')[0].style['stroke']
    for (var i = 0; i < data.points[0].data.x.length; i += 1) {
      colors.push(base_color)
    };
    colors[data.points[0].pointNumber] = '#FF00FF';
    Plotly.restyle(el, 
                   {'marker':{color: colors}}, 
                   [data.points[0].curveNumber]
                  );
    //make sure all the other traces get back their original color
    for (i = 0; i < document.getElementsByClassName('plotly')[0].data.length; i += 1) {
      if (i != data.points[0].curveNumber) {
        colors = [];
        base_color = document.getElementsByClassName('legendpoints')[i].getElementsByTagName('path')[0].style['stroke'];
        for (var p = 0; p < document.getElementsByClassName('plotly')[0].data[i].x.length; p += 1) {
          colors.push(base_color);
        }
        Plotly.restyle(el, 
                       {'marker':{color: colors}}, 
                       [i]);
      }
    };
  });
}"
server <- function(input, output, session) {

  nms <- row.names(mtcars)

  output$plot <- renderPlotly({
    p <- ggplot(mtcars, aes(x = mpg, y = wt, col = as.factor(cyl), key = nms)) + 
      geom_point()
    ggplotly(p) %>% onRender(javascript)

  })
}

shinyApp(ui, server)

一些解释:

  • Plotly 的事件,例如plotly_click 在事件函数中传递一些信息(本例中为data
  • data.points 包含触发事件的点
  • 在这种情况下,我们只有一个点data.points[0],其中pointNumber 是原始数组的索引,curveNumber 是跟踪号。
  • 绘图将所有输入数据存储在绘制绘图的div
  • 我们可以通过document.getElementsByClassName('plotly')[0].data访问它
  • 可以通过document.getElementsByClassName('legendpoints')[i] 访问图例,其中i 是图例的索引
  • ggplotly 或 plot_ly 返回 htmlwidgets
  • 可以使用任何 htmlwidget functions 添加 Javascript 或 HTML 代码,例如onrender 在这种情况下

【讨论】:

  • 谢谢。它工作出色(+1)。在我最初的用例中,变量中有 50 多个级别,magenta 很有可能是其中之一。在这种情况下,将难以识别所选点。你觉得还有其他选择吗? (您的答案中有一个小错字plotlyOutput("plot"), 逗号不应出现)。
  • 感谢您从代码编辑中找到剩余部分!您还可以更改大小,例如sizes.push(10);... sizes[...pointNumber] = 20;... 'marker': {size: sizes}
  • (忘了问另一个我想到的问题)为什么我能够为每个因子水平突出一个点?在上面的图中,我最多可以突出显示三个点(每个点属于cyl==4cyl==6cyl==8)。我想在它消失之前突出显示每个点最多一个点以突出显示下一个点击点。你有什么想法?
  • 正确的做法是重新设置所有痕迹/因素的样式。在示例中,仅对来自单击点的跟踪进行了重新样式化,我将缺少的代码添加到示例中。
  • 能否请您指出我可以理解您的代码并建立在您暗示的方向上的来源?我想看看可以提取哪些其他组件以及如何修改它们。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 2011-08-01
  • 2017-07-06
  • 2020-05-31
  • 2012-09-09
  • 2017-05-20
相关资源
最近更新 更多