2016-11-25 14 views
7

मैं चमकदार की मूल बातें से परिचित हूं लेकिन यहां कुछ के साथ संघर्ष कर रहा हूं। उस बिंदु को हाइलाइट करने के लिए जब कोई बिंदु क्लिक किया जाता है तो मैं एक ggplot परत जोड़ने में सक्षम होना चाहता हूं। मुझे पता है कि यह ggvis के साथ संभव है और गैलरी में एक अच्छा उदाहरण है, लेकिन मैं ui इनपुट के रूप में क्लिक को कैप्चर करने के लिए nearPoints() का उपयोग करने में सक्षम होना चाहता हूं।निकट बिंदुओं के साथ चमकदार गतिशील ggplot परतें()

मैंने कुछ कोशिश की है (नीचे देखें) जो ggplot परत से अलग काम करता है और फिर गायब हो जाता है। मैंने reactive(), eventReactive() और इसी तरह के सभी प्रकार के संपादनों की कोशिश की है।

किसी भी मदद की बहुत सराहना की है ...

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) 
    }) 
    }) 
) 

मुझे लगता है कि मैं समझता हूँ कि धारणात्मक क्यों यह काम नहीं करता। साजिश पर input$clicked पर निर्भरता है जिसका अर्थ है कि जब input$clicked साजिश पुनः प्रस्तुतकर्ताओं को बदलता है लेकिन यह बदले में input$clicked रीसेट करता है। एक पकड़ 22 स्थिति की बिट।

उत्तर

8

कृपया, इस प्रयास करें:

दृष्टिकोण 1 (अनुशंसित)

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) 
    }) 
    }) 
) 

आप एक बिंदु एक बार यह हाइलाइट किया गया है पर क्लिक करें। यदि आप इसे दूसरी बार क्लिक करते हैं तो हाइलाइट फिर से बंद हो जाता है (टॉगलिंग)।

कोड वास्तव में हाइलाइट किए गए (चयनित) अंक और एक प्रतिक्रियाशील अभिव्यक्ति selected() स्टोर करने के लिए वैश्विक चर selected_points का उपयोग करता है जो किसी भी बिंदु पर क्लिक होने पर वैश्विक चर अद्यतन करता है।

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(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) 
    }) 
    }) 
) 
बेशक

, आप प्रतिक्रियाशील फ़ंक्शन selected() पर कॉल करने के बजाय वैश्विक चर selected_points सीधे ggplot कॉल में उपयोग कर सकते हैं। हालांकि, आपको यह सुनिश्चित करना होगा कि renderPlot() निष्पादित किया जाता है जब भी input$clicked बदल जाता है। इसलिए, input$clicked को डमी संदर्भ renderPlot() के भीतर कोड में शामिल किया जाना है।

अब, प्रतिक्रियाशील फ़ंक्शन selected() की आवश्यकता नहीं है और इसे observe() अभिव्यक्ति द्वारा प्रतिस्थापित किया जा सकता है। reactive() के विपरीत, observe() कोई मान नहीं देता है। जब भी input$clicked संशोधित होता है तो यह वैश्विक चर selected_points अपडेट करता है।

दृष्टिकोण 3 (प्रतिक्रियाशील मान)

यह दृष्टिकोण एक वैश्विक चर बचा जाता है। इसके बजाय, यह प्रतिक्रियाशील प्रोग्रामिंग के लिए विशेष क्षमताओं के साथ सूची-जैसी वस्तु rv बनाने के लिए reactiveValues का उपयोग करता है (?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) 
    }) 
    }) 
) 

, कृपया ध्यान दें कि rv को observer हिस्सा संदर्भ में isolate() में संक्षिप्त करने के लिए सुनिश्चित करें कि केवल input$clicked में परिवर्तन observer में कोड के निष्पादन को गति प्रदान करेगा की जरूरत है। अन्यथा, हम एक अंतहीन पाश प्राप्त करेंगे। renderPlot का निष्पादन तब भी ट्रिगर होता है जब प्रतिक्रियाशील मान rv बदल जाता है।

निष्कर्ष

व्यक्तिगत रूप से, मैं प्रतिक्रियाशील कार्य करता है जो निर्भरता (प्रतिक्रियात्मकता) अधिक स्पष्ट बनाने का उपयोग कर दृष्टिकोण 1 पसंद करते हैं। मुझे दृष्टिकोण 2 कम अंतर्ज्ञानी में क्लिक किए गए इनपुट इनपुट करने के लिए डमी कॉल मिलती है। दृष्टिकोण 3 को प्रतिक्रियाशीलता की पूरी तरह से समझने और सही स्थानों पर isolate() का उपयोग करने की आवश्यकता है।

+0

धन्यवाद कि यह सही है। सबसे पहले मुझे समझ में नहीं आया कि दूसरी 'geom_point' परत में डेटा स्रोत' चयनित() 'क्यों है, लेकिन अब मैं देख सकता हूं कि 'चयनित()' फ़ंक्शन 'select_points' ऑब्जेक्ट देता है। ब्याज से बाहर, क्या मेरे पास डेटा स्रोत के रूप में 'select_points' हो सकता है और ऑब्जेक्ट को फ़ंक्शन से वापस नहीं कर सकता? यदि हां, तो आप इसे दूसरे तरीके से क्यों करेंगे? – roman

+1

ठीक है, यह प्रतिक्रियाशीलता के बारे में है या किसी विशेष डेटा को बदलते समय कोड का किस टुकड़ा निष्पादित किया जाएगा (प्रतिक्रियाशीलता)। हां, आप 'select_points' का उपयोग कर सकते हैं लेकिन आपको' इनपुट $ क्लिक 'पर डमी कॉल जोड़कर प्रतिक्रियाशीलता को लागू करना होगा (मेरे संपादित उत्तर के _Approach 2_ देखें)। मैं प्रतिक्रियाशील कार्यों का उपयोग करना पसंद करता हूं जो निर्भरताओं को अधिक स्पष्ट बनाते हैं। विस्तारित उत्तर के लिए – Uwe

+0

धन्यवाद - बहुत उपयोगी। – roman

संबंधित मुद्दे