2013-06-23 12 views
21

संशोधित करने की अनुमति देता है यह अभी तक एक व्यावहारिक प्रश्न नहीं बल्कि एक सैद्धांतिक है। मैं एक कच्चे डेटा को एक इंटरैक्टिव तरीके से प्रदर्शित करने के लिए चमक का उपयोग करने की सोच रहा था। यह ठीक है।चमकदार आर एप्लिकेशन जो उपयोगकर्ताओं को डेटा

हालांकि - क्या उपयोगकर्ताओं को प्रदर्शित होने वाले डेटा को बदलना संभव है?

कहें, अगर मेरे पास अंतर्निहित डेटा को कुछ शर्तों को पूरा करने के लिए अंतर्निहित डेटा को प्रतिबंधित करने के लिए स्लाइडर्स का एक गुच्छा है और इन अवलोकनों को प्रदर्शित किया गया है - क्या यह संभव है कि उपयोगकर्ताओं को उस डेटा में संशोधन करने दें और इन संशोधनों को वापस भेज दिया जाए सर्वर, जो बदले में इन परिवर्तनों को बचाता है?

मैं उन परिदृश्यों के बारे में सोच रहा हूं जहां उपयोगकर्ता डेटा के माध्यम से ब्राउज़ करने और डेटा में संभावित आउटलेटर्स का पता लगाने के लिए चमकदार एप्लिकेशन का उपयोग कर सकते हैं - उपयोगकर्ता इन्हें आउटलाइन के रूप में फ़्लैग कर सकता है। हालांकि, उस जानकारी को सर्वर पर वापस भेजना होगा।

क्या ऐसा कोई एप्लिकेशन संभव है? क्या कुछ मौजूदा उदाहरण हैं?

+1

मुझे लगता है कि कठिनाई एक संपादन योग्य डेटा तालिका है, मुझे मौजूदा नहीं पता है। हमारे पास ऐसी प्रदर्शित और संपादन योग्य डेटा तालिका होने पर जानकारी सर्वर पर वापस जा सकती है। – Zhenglei

उत्तर

18

आप मूल रूप से चमकदार में लगभग कुछ भी के बाद से आप अपने खुद के input और output बाइंडिंग – तो अपने प्रश्न का उत्तर हां, तो आप पूछ रहे हैं संभव है बना सकते हैं कर सकते हैं। मान लें कि आपके पास एक डेटा फ्रेम है जिसे आप उपयोगकर्ता द्वारा देखे जाने वाले वेब पेज पर भेजते हैं। उदाहरण के तौर पर, आप उपयोगकर्ताओं को एक सेल पर क्लिक करने की अनुमति देना चाहते हैं यदि यह एक बाहरी है जिसे हटाया जाना चाहिए (NA के साथ प्रतिस्थापित)।

मान लीजिए कि डेटा फ्रेम इस तरह दिखता है:

x <- data.frame(Age = c(10, 20, 1000), Weight = c(120, 131, 111)) 
x 

# Age Weight 
# 10  120 
# 20  131 
# 1000 111 

चमकदार आप एक सामान्य HTML तालिका जो कुछ इस तरह जब वेबपृष्ठ पर प्रदर्शित लग सकता है बनाएगी से:

<table class="outlier-finder" id="outliers"> 
    <tr> 
    <td>Age</td> 
    <td>Weight</td> 
    </tr> 
    <tr> 
    <td>10</td> 
    <td>120</td> 
    </tr> 
    <tr> 
    <td>20</td> 
    <td>131</td> 
    </tr> 
    <tr> 
    <td>1000</td> 
    <td>111</td> 
    </tr> 
</table> 

अब तोड़ने jQuery को बाहर करें और एक क्लिक ईवेंट को बाध्य करें ताकि जब एक सेल क्लिक किया जाता है तो आप पंक्ति और कॉलम नंबर (see here) रिकॉर्ड कर सकते हैं और उसके बाद उस सेल को NA चमकदार में बदल सकते हैं। आपका इनपुट बाध्यकारी (see here for details of what's going on here) की तरह कुछ दिख सकता है:

$(document).on("click", ".outlier-finder td", function(evt) { 

    // Identify the clicked cell. 
    var el = $(evt.target); 

    // Raise an event to signal that the something has been selected. 
    el.trigger("change"); 

}); 

var cell_binding = new Shiny.InputBinding(); 

$.extend(cell_binding, { 

    find: function(scope) { 
    return $(scope).find(".outlier-finder td"); 
    }, 

    getValue: function(el) { 
    // Get the row and cell number of the selected td. 
    var col = el.parent().children().index(el); 
    var row = el.parent().parent().children().index(el.parent()); 
    var result = [row, col]; 
    return result; 
    }, 

    setValue: function(el, value) { 
    $(el).text(value); 
    }, 

    subscribe: function(el, callback) { 
    $(el).on("change.cell_binding", function(e) { 
     callback(); 
    }); 
    }, 

    unsubscribe: function(el) { 
    $(el).off(".cell_binding"); 
    } 

}); 

Shiny.inputBindings.register(cell_binding); 

वहाँ एक बहुत यहाँ चल रहा है, लेकिन आम तौर पर इन इनपुट बाइंडिंग काफी एक दूसरे के समान हैं। सबसे महत्वपूर्ण बात setValue() फ़ंक्शन है। वहां क्या हो रहा है (यह अनचाहे है) क्लिक किया जा रहा सेल की पंक्ति और कॉलम संख्या रिकॉर्ड की गई है और सर्वर पर वापस पोस्ट की गई है।

तो शाइनी से आप बस की तरह कुछ करना होगा:

updateData <- reactive({ 

    # Get selection 
    remove_outlier <- as.integer(RJSONIO::fromJSON(input$outliers)) 

    if (!is.null(remove_outlier)) { 

     # Remove that outlier. 
     x[remove_outlier[1], remove_outlier[2]] <- NA 

    } 

    return(x) 

}) 

output$outliers <- renderText({ 

    # Update x. 
    current_x <- updateData() 

    # Write code to output current_x to page. 
    # ... 
    # ... 

}) 

आप शायद एक आउटपुट उत्पादन $ बाहरी कारकों के लिए बाध्यकारी रूप में अच्छी तरह करने की आवश्यकता होगी। यह स्पष्ट रूप से यहां सरल कोड है, आपको त्रुटि जांच आदि लागू करने की आवश्यकता होगी

यह सिर्फ एक उदाहरण है। हकीकत में, संभवत: आपके उपयोगकर्ता द्वारा परिवर्तन किए जाने पर हर बार आपके डेटा फ्रेम को चमकने के लिए चमकदार नहीं होगा। आप कुछ प्रकार के सबमिट बटन चाहते हैं ताकि एक बार जब उपयोगकर्ता ने अपने सभी बदलाव किए हों तो उन्हें लागू किया जा सकता है।


मैं भी दूर से इस के किसी भी परीक्षण नहीं किया तो वहाँ लगभग निश्चित रूप से कुछ त्रुटियाँ हैं। लेकिन चूंकि आप सिर्फ सैद्धांतिक प्रश्न पूछ रहे थे, मैंने इसे बहुत अधिक नहीं देखा।सामान्य रणनीति वैसे भी काम करना चाहिए। इनपुट बाइंडिंग के साथ आप किसी वेब पेज से सर्वर पर वापस और आउटपुट बाइंडिंग के विपरीत कुछ भी प्राप्त कर सकते हैं। हो सकता है कि "कुछ भी" एक खिंचाव — है लेकिन आप बहुत कुछ कर सकते हैं।

0

मैं एक पैकेज इस वर्कफ़्लो का उपयोग करता है पर काम कर रहा है:

  1. आर सत्र में उपयोगकर्ता लोड डेटा और कमांड लाइन
  2. डेटा एक चमकदार एप्लिकेशन को पारित कर दिया है से कुछ प्रारंभिक जांच पूरा करता है जो उपयोगकर्ता को
  3. उपयोगकर्ता को इंटरैक्टिव रूप से चुनने और संशोधित करने की अनुमति देता है, उपयोगकर्ता चमकदार सत्र को समाप्त करने के लिए एक बटन पर क्लिक करता है, और संशोधित डेटा आर सत्र में वापस आ जाता है, उपयोगकर्ता द्वारा किए गए सभी परिवर्तनों के साथ।

यह हमेशा की तरह चमकदार प्रयोग किया जाता है नहीं है - एप्लिकेशन दूर से तैनात नहीं किया जा रहा है, लेकिन बजाय एक एकल उपयोगकर्ता के लिए एक इंटरैक्टिव अंकन इंटरफेस के रूप में सेवा करने के लिए स्थानीय स्तर पर किया जाता है। मैंने बेस ग्राफिक्स और locator() फ़ंक्शन के साथ समान चीजें की हैं, जो थकाऊ है। टीसीएल/टीके का उपयोग करना आसान हो सकता है, लेकिन यह देखने के लिए उत्सुक था कि यह चमकदार के साथ कैसे काम कर सकता है।

यहाँ एक खिलौना उदाहरण है:

myShiny <- function(mydata){ 

    ui <- fluidPage(
    actionButton("exit", label = "Return to R"), 
    plotOutput("dataPlot", click = "pointPicker") 
) 

    server <- function(input, output){ 
    output$dataPlot <- renderPlot({ 
     plot(x = myData()[, 1], y = myData()[,2], cex = myData()[,3]) 
    }) 

    myData <- reactive({ 
     selPts <- nearPoints(mydata, 
          input$pointPicker, "x", "y", 
          threshold = 25, maxpoints = 1, allRows = TRUE) 
     if(sum(selPts[,"selected_"]) > 0){ 
     ## use '<<-' to modify mydata in the parent environment, not the 
     ## local copy 
     mydata[which(selPts[, "selected_", ]), "size"] <<- 
      mydata[which(selPts[, "selected_", ]), "size"] + 1 
     } 
     mydata 
    }) 

    observe({ 
     if(input$exit > 0) 
     stopApp() 
    }) 

    } 
    runApp(shinyApp(ui = ui, server = server)) 
    return(mydata) 
} 

testDF <- data.frame(x = seq(0, 2 * pi, length = 13), 
        y = sin(seq(0, 2 * pi, length = 13)), 
        size = rep(1, 13)) 

modDF <- myShiny(testDF) 

shiny-app

इस मामले में, एक बिंदु पर क्लिक (जो कल्पना है स्तंभों में से एक ("आकार") इसी पंक्ति में का मूल्य बढ़ जाता प्लॉट किए जाने पर cex तर्क का उपयोग करना)। मूल्यों, इस मामले में उपयोगकर्ता के लिए वापस आ रहे हैं और, modDF चर में संग्रहीत:

> modDF 
      x    y size 
1 0.0000000 0.000000e+00 1 
2 0.5235988 5.000000e-01 5 
3 1.0471976 8.660254e-01 1 
4 1.5707963 1.000000e+00 1 
5 2.0943951 8.660254e-01 2 
6 2.6179939 5.000000e-01 1 
7 3.1415927 1.224647e-16 1 
8 3.6651914 -5.000000e-01 7 
9 4.1887902 -8.660254e-01 1 
10 4.7123890 -1.000000e+00 1 
11 5.2359878 -8.660254e-01 3 
12 5.7595865 -5.000000e-01 1 
13 6.2831853 -2.449294e-16 1 

यह इस संशोधित करने के लिए (एक 'बाहरी' स्तंभ में मान टॉगल करने के लिए इतना है कि आप रिवर्स सकता है आसान होगा आपके निर्णय), या सीधे डेटा फ्रेम में स्थायी परिवर्तन करने के लिए।

मेरे वास्तविक पैकेज में, मैं इस दृष्टिकोण का उपयोग करता हूं ताकि उपयोगकर्ता गैर-रैखिक प्रतिगमन के लिए प्रारंभिक पैरामीटर का चयन कर सके, तुरंत ब्राउज़र में प्लॉट किए गए परिणामी मॉडल फिट को देखें, तब तक दोहराएं जब तक उन्हें समझदार दिखने वाला एक उपयुक्त मॉडल न मिल जाए , और अंत में परिणाम बचाएं और अपने आर सत्र में वापस आएं।

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