动态ggplot图层闪亮nearPoints() [英] dynamic ggplot layers in shiny with nearPoints()

查看:144
本文介绍了动态ggplot图层闪亮nearPoints()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我熟悉闪亮的基础知识,但在这里挣扎着。我希望能够添加一个ggplot图层,当一个点被点击时突出显示该点。我知道这可能与ggvis,并在画廊有一个很好的例子,但我希望能够使用 nearPoints()捕获点击作为用户界面输入。



我尝试了一些东西(见下文),它与ggplot层分离,然后消失。我尝试过对 reactive() eventReactive()等进行各种编辑。



任何帮助非常感谢......

  library(shiny)
库(ggplot2)
$ b $ shinyApp(
ui = shinyUI(
plotOutput(plot,click =clicked)
),

server = shinyServer(function(input,output){
output $ plot< - renderPlot({
ggplot(mtcars,aes(x = mpg,y = wt))+
geom_point()+
geom_point(data = nearPoints(mtcars,input $ clicked),color =red,size = 5)
})
})

我想我理解这是行不通的。该图依赖于输入$ clicked ,这意味着当输入$点击时改变绘图重新渲染,但是这个依次重置输入$点击

解决方案

请试试这个:



< h1>方法1(推荐)

 库(闪亮)
库(ggplot2)

#初始化全局变量以记录所选行(单击)
selected_points < b ui = shinyUI(
plotOutput(plot,click =clicked)
),

server = shinyServer(function(input,output){

selected < - 反应性({
#添加点击
selected_points<< - rbind(selected_points,nearPoints(mtcars,input $ clicked))
#remove _all_ duplicates if任何(切换模式)
#http://stackoverflow.com/a/13763299/3817004
selected_points<< -
selected_points [!(duplicated(selected_points)|
重复(selected_points,fromLast = TRUE)),]
str(selected_point s)
return(selected_points)
})

输出$ plot < - renderPlot({
ggplot(mtcars,aes(x = mpg,y = wt ))+
geom_point()+
geom_point(data = selected(),color =red,size = 5)
})
})

如果您每次点击一个点,它都会高亮显示。如果再次单击它,突出显示会再次关闭(切换)。



代码使用全局变量 selected_points 存储实际突出显示的点(选定)和一个反应表达式 selected(),该点更新全局变量,每当一个点被点击时。

str(selected_points)可能有助于显示工作状态,但可以删除。

方法2(可选)



使用 observe()而不是 reactive()并直接引用全局变量 selected_points ,而不是从函数返回对象:

  library(shiny)
library(ggplot2)

selected_points< - mtcars [0,]
str (selected_points)


shinyApp(
ui = shinyUI(
plotOutput(plot,click =clicked)
),

server = shinyServer(fu (输入,输出){

观察({
#add clicked
selected_points<< - rbind(selected_points,nearPoints(mtcars,input $ clicked))
#remove _all_ duplicates(toggle)
#http://stackoverflow.com/a/13763299/3817004
selected_points<< -
selected_points [!(duplicated(selected_points)|
duplicated(selected_points,fromLast = TRUE)),]
str(selected_points)
})

输出$ plot< - renderPlot({
#下一个语句是反应性需要
输入$单击
ggplot(mtcars,aes(x = mpg,y = wt))+
geom_point()+
geom_point(data = selected_points,color =red,size = 5)
})
})

当然,您可以直接在 ggplot 调用中使用全局变量 selected_points 调用被动函数 selected()。但是,只要 input $ clicked 发生更改,您必须确保执行 renderPlot()。因此,必须在 renderPlot()中的代码中包含对 input $ clicked 的虚引用。



现在,被动函数 selected()不再需要,可以用观察代替()表达式。与 reactive()不同, observe()不返回值。只要修改了 input $ clicked ,它就会更新全局变量 selected_points

方法3(反应值)



这种方法避免了全局变量。相反,它使用 reactiveValues 创建一个类似列表的对象 rv ,它具有反应式编程的特殊功能(请参阅<$ c

$ p $库$
库(ggplot2)
$ b shinyApp(
ui = shinyUI(
plotOutput(plot,click =clicked)
),

server = shinyServer(函数(输入,输出){

rv < - reactiveValues(selected_points = mtcars [0,])

观察({
#add clicked
rv $ selected_points< - rbind(isolate(rv $ selected_points),
nearPoints(mtcars,input $ clicked))
#remove _all_ duplicates(toggle)
#http:/ /stackoverflow.com/a/13763299/3817004
rv $ selected_points< - isolate(
rv $ selected_points [!(duplicated(rv $ selected_points)|
duplicated(rv $ selected_points,fromLast = TRUE)),])
str(rv $ sel ect_point)
})

输出$ plot < - renderPlot({
ggplot(mtcars,aes(x = mpg,y = wt))+
geom_point ()+
geom_point(data = rv $ selected_points,color =red,size = 5)
})
})

请注意,在观察者部分引用 rv 需要封装在 isolate()中,以确保只改变输入$点击会触发观察者中代码的执行。否则,我们会得到一个无限循环。执行 renderPlot 会在被动值 rv 发生变化时触发。



结论



就个人而言,我更喜欢使用反应函数的方法1,这使得依赖性(反应性)更加明确。我发现在方法2中输入$点击的虚拟调用较不直观。方法3需要彻底了解反应性,并在正确的地方使用 isolate()


I'm familiar with the basics of shiny but struggling with something here. I would like to be able to add a ggplot layer when a point is clicked to highlight that point. I know this is possible with ggvis and there is a nice example in the gallery, but I would like to be able to use nearPoints() to capture the click as ui input.

I have tried something (see below) which works apart from the ggplot layer appears and then disappears. I have tried all kinds of edits to this with reactive(), eventReactive() and so on.

Any help is much appreciated...

library(shiny)
library(ggplot2)

shinyApp(
  ui = shinyUI(
        plotOutput("plot", click = "clicked")
    ),

  server = shinyServer(function(input, output) {
    output$plot <- renderPlot({
      ggplot(mtcars, aes(x = mpg, y = wt)) +
        geom_point() +
        geom_point(data = nearPoints(mtcars, input$clicked), colour = "red", size = 5)
    })
  })
)

I think I understand conceptually why this doesn't work. The plot has a dependency on input$clicked which means that when input$clicked changes the plot re-renders but this in turn resets input$clicked. Bit of a catch 22 situation.

解决方案

Please, try this:

Approach 1 (recommended)

library(shiny)
library(ggplot2)

# initialize global variable to record selected (clicked) rows
selected_points <- mtcars[0, ]
str(selected_points)


shinyApp(
  ui = shinyUI(
    plotOutput("plot", click = "clicked")
  ),

  server = shinyServer(function(input, output) {

    selected <- reactive({
      # add clicked
      selected_points <<- rbind(selected_points, nearPoints(mtcars, input$clicked))
      # remove _all_ duplicates if any (toggle mode) 
      # http://stackoverflow.com/a/13763299/3817004
      selected_points <<- 
        selected_points[!(duplicated(selected_points) | 
                            duplicated(selected_points, fromLast = TRUE)), ]
      str(selected_points)
      return(selected_points)
    })

    output$plot <- renderPlot({
      ggplot(mtcars, aes(x = mpg, y = wt)) +
        geom_point() +
        geom_point(data = selected(), colour = "red", size = 5)
    })
  })
)

If you click a point one time it is highlighted. If you click it a second time the highlight is turned off again (toggling).

The code uses a global variable selected_points to store the actually highlighted (selected) points and an reactive expression selected() which updates the global variable whenever a point is clicked.

The str(selected_points) may help to visualize the working but can be removed.

Approach 2 (alternative)

There is a slightly different approach which uses observe() instead of reactive() and references the global variable selected_points directly instead of returning the object from a function:

library(shiny)
library(ggplot2)

selected_points <- mtcars[0, ]
str(selected_points)


shinyApp(
  ui = shinyUI(
    plotOutput("plot", click = "clicked")
  ),

  server = shinyServer(function(input, output) {

    observe({
      # add clicked
      selected_points <<- rbind(selected_points, nearPoints(mtcars, input$clicked))
      # remove _all_ duplicates (toggle)
      # http://stackoverflow.com/a/13763299/3817004
      selected_points <<- 
        selected_points[!(duplicated(selected_points) | 
                            duplicated(selected_points, fromLast = TRUE)), ]
      str(selected_points)
    })

    output$plot <- renderPlot({
      # next statement is required for reactivity
      input$clicked
      ggplot(mtcars, aes(x = mpg, y = wt)) +
        geom_point() +
        geom_point(data = selected_points, colour = "red", size = 5)
    })
  })
)

Of course, you can use the global variable selected_points directly in the ggplot call instead of calling the reactive function selected(). However, you have to ensure that renderPlot() is executed whenever input$clicked is changed. Therefore, the dummy reference to input$clicked has to be included in the code within renderPlot().

Now, the reactive function selected() is no longer needed and can be replaced by an observe() expression. As opposed to reactive(), observe() doesn't return a value. It just updates the global variable selected_points whenever input$clicked is modified.

Approach 3 (reactive values)

This approach avoids a global variable. Instead, it uses reactiveValues to create a list-like object rvwith special capabilities for reactive programming (see ?reactiveValues).

library(shiny)
library(ggplot2)

shinyApp(
  ui = shinyUI(
    plotOutput("plot", click = "clicked")
  ),

  server = shinyServer(function(input, output) {

    rv <- reactiveValues(selected_points = mtcars[0, ])

    observe({
      # add clicked
      rv$selected_points <- rbind(isolate(rv$selected_points), 
                                           nearPoints(mtcars, input$clicked))
      # remove _all_ duplicates (toggle)
      # http://stackoverflow.com/a/13763299/3817004
      rv$selected_points <- isolate(
        rv$selected_points[!(duplicated(rv$selected_points) | 
                               duplicated(rv$selected_points, fromLast = TRUE)), ])
      str(rv$selected_points)
    })

    output$plot <- renderPlot({
      ggplot(mtcars, aes(x = mpg, y = wt)) +
        geom_point() +
        geom_point(data = rv$selected_points, colour = "red", size = 5)
    })
  })
)

Please, note that in the observer part references to rv need to be encapsulated in isolate() to ensure that only changes to input$clicked will trigger execution of the code in observer. Otherwise, we'll get an endless loop. Execution of renderPlot is triggered whenever the reactive value rv is changed.

Conclusion

Personally, I prefer approach 1 using reactive functions which make the dependencies (reactivity) more explicit. I find the dummy call to input$clicked in approach 2 less intuitive. Approach 3 requires a thorough understanding of reactivity and using isolate() in the right places.

这篇关于动态ggplot图层闪亮nearPoints()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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