2013-06-23 131 views
21

這還不是一個實際問題,而是一個理論問題。我正在考慮使用Shiny以交互方式顯示一些原始數據。這可以。允許用戶修改數據的Shiny R應用程序

但是 - 是否有可能讓用戶更改顯示的數據?如果我有一堆滑塊讓用戶限制底層數據以滿足某些條件並顯示這些觀察值 - 是否可以允許用戶對該數據進行修改並將這些修改發送回服務器,從而保存這些變化?

我想到的情況下,用戶可以使用一個閃亮的應用程序通過數據瀏覽和數據檢測潛在的異常值 - 然後用戶可以標記這些異常值。但是,該信息需要傳回服務器。

是這樣的應用程序可能嗎?有一些現有的例子嗎?

+1

我想難度是有一個可編輯的數據表,我不知道現有的一個。一旦我們有這樣一個顯示和可編輯的數據表,信息可以傳回服務器。 – Zhenglei

回答

18

你基本上可以做閃亮的幾乎所有的東西,因爲你可以創建自己的inputoutput綁定–所以回答你的問題是肯定的,你要問是可能的。假設你有一個你發送到網頁的數據框供用戶查看。舉個例子,你想允許用戶只需單擊單元格,如果它是應該被刪除的異常值(與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. 
    # ... 
    # ... 

}) 

你可能會需要做的輸出以及輸出$離羣結合。這是簡化的代碼在這裏很明顯,你將需要申請錯誤檢查等

這僅僅是一個例子。實際上,當用戶每次更改數據時,您都可能不會Shiny更新數據框。你會想要某種提交按鈕,以便一旦用戶完成了他/她的所有更改,就可以應用它們。


我還沒有遠程測試任何這,這樣幾乎肯定一些錯誤。但既然你只是在問一個理論問題,我沒有太多的檢查。無論如何,一般的策略都應該起作用。使用輸入綁定,您可以從網頁獲取任何內容返回到服務器,反之亦然,輸出綁定。也許說什麼「什麼」是一個延伸—但你可以做很多事情。

0

我一直在使用該工作流包:

  1. 用戶將數據加載到R對話並完成從命令行
  2. 的數據被傳遞到一個閃亮應用中的一些初步篩選它允許用戶交互式地選擇和修改數據,用戶點擊一個按鈕來結束閃亮的會話,並且修改後的數據返回到R會話,並且用戶所做的所有更改都保持不變。

這不是通常的方式Shiny被使用 - 應用程序沒有被遠程部署,而是被本地用作單個用戶的交互式繪圖界面。我用基本圖形和locator()函數做了類似的事情,這很枯燥。使用tcl/tk可能更容易,但我很好奇,看看它如何與Shiny配合使用。

這裏的一個玩具例如:

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 

這將是很容易修改這在「異常」列切換數值(這樣你可以扭轉你的決定),還是直接對數據框進行永久性修改。

在我實際的包,我用這種方式來讓用戶直觀地選擇初始參數的非線性迴歸,立即看到結果模型擬合在瀏覽器中繪製,重複,直到他們得到一個擬合模型,看起來明智,最後保存結果並返回到他們的R會話。

相關問題