2016-08-18 78 views
-1

目標:我想讓用戶上傳他們自己的數據框,指定他們的數據框中提供「名稱」,「經度」和「緯度」數據,然後使用DataTable創建表(DT包)。(閃亮)「錯誤:[on_request_read]解析錯誤」

問題:用戶進行選擇後,數據幀出現在渲染表上,但是當他們嘗試對每列進行排序或與數據交互時,甚至更改「名稱」,「經度」或「緯度」,在控制檯上會出現以下錯誤信息:

ERROR: [on_request_read] parse error 

這裏是我的UI和服務器的網頁我有代碼(注:我使用的佈局dashboardPage):

重複的例子,

ui <- dashboardPage(

    dashboardHeader(title = "Test") , 

    dashboardSidebar(
    sidebarMenu(
     menuItem("Selections", tabName = "selections"), 
     menuItem("Data Table", tabName = "dataTable") 
    ) 
), 

    dashboardBody(
    tabItems(
     tabItem(
     tabName = "selections", 
     selectInput("mapChoice", 
        label = "Choose a map:", 
        choices = c("", 
           "New Map from Data Table"), 
        selected = ""), 

     conditionalPanel("input.mapChoice == 'New Map from Data Table'", 
      fileInput("userData", 
        label = "Choose CSV File", 
        accept=c('text/csv', 
          'text/comma-separated-values,text/plain', 
          '.csv')),    

      uiOutput("newMapUI") 
     ), 
     ############################################### 
     # Bookmark widget 
     shinyURL.ui(width = "400px") 
     ############################################### 
    ), 

     tabItem(
     tabName = "dataTable", 
     DT::dataTableOutput("table") 
    ) 
    ) 
) 


) 


server <- function(input, output, session) { 
    ############################################################ 
    # Add in function for saving and recording urls as bookmarks 
    shinyURL.server(session) 
    ############################################################ 

    userData <- reactive({ 

    path <- input$userData 

    if (is.null(path)) 
     return (NULL) 

    results <- read.csv(file = path$datapath, 
         header = TRUE, 
         stringsAsFactors = FALSE) 
    results 

    }) 

    output$newMapUI <- renderUI({ 


    list(

     # Specify the column for labeling 
     if (!is.null(userData())) { 
     selectizeInput("nameCol", 
         label = "Choose the column to be used for 
         point labels: ", 
         choices = c(names(userData())), 
         multiple = TRUE, 
         options = list(placeholder = 'Name', 
             maxItems = 1)) 
     }, 

     # Specify longitude column 
     if (!is.null(userData())) { 
     selectizeInput("lonCol", 
         label = "Choose the column containing longitude 
         values: ", 
         choices = c(names(userData())), 
         multiple = TRUE, 
         options = list(placeholder = 'Longitude', 
             maxItems = 1)) 
     }, 
     # Specify latitude column 
     if (!is.null(userData())) { 
     selectizeInput("latCol", 
         label = "Choose the column conatining latitude 
         values: ", 
         choices = c(names(userData())), 
         multiple = TRUE, 
         options = list(placeholder = 'Latitude', 
             maxItems = 1)) 
     } 

    ) 



    }) 

    nameCol <- reactive({ 
    as.character(input$nameCol) 
    }) 

    lonCol <- reactive({ 
    as.character(input$lonCol) 
    }) 

    latCol <- reactive({ 
    as.character(input$latCol) 
    }) 



    newUserData <- reactive({ 

    if (is.null(userData())) 
     return (NULL) 

    # Create the new data frame: 
    if (length(nameCol()) != 0 && 
     length(lonCol()) != 0 && 
     length(latCol()) != 0) { 

     userData <- userData() 

     name <- nameCol() 
     lonCol <- lonCol() 
     latCol <- latCol() 

     results <- data.frame(Name = userData[, name], 
          Longitude = userData[, lonCol], 
          Latitude = userData[, latCol]) 

     results$Name <- as.character(results$Name) 
     results$Longitude <- as.numeric(results$Longitude) 
     results$Latitude <- as.numeric(results$Latitude) 

    } 

    results 

    }) 

    mapData <- reactive({ 

    data <- data.frame() 

    if (input$mapChoice == "New Map from Data Table") { 

     if (length(nameCol()) != 0 && 
      length(lonCol()) != 0 && 
      length(latCol() != 0)) { 
     data <- newUserData() 
     } 
    } 
     data 
    }) 

    output$table <- DT::renderDataTable({ 

    datatable(mapData(), 
       extensions = c('Buttons', 'FixedHeader', 'Scroller'), 
       options = list(dom = 'Bfrtip', 
          buttons = list('copy', 'print', 
              list(extend = 'csv', 
               filename = 'map data', 
               text = 'Download') 
          ), 
          scrollX = TRUE, 
          pageLength = nrow(mapData()), 
          fixedHeader = TRUE, 
          deferRender = FALSE, 
          scrollY = 400, 
          scroller = FALSE, 
          autowidth = TRUE 
      ) 
    ) 

    } 
) # End of table render 

    } 

shinyApp(ui = ui, server = server) 

注意:如果我試圖將這些數據用於繪圖,那也是行不通的。 (繪製地圖上的點是我的最終目標)。

更新1:由於某些愚蠢的原因,這個片段應用程序運行得如預期般完美,但這些代碼行直接來自我的應用程序。隨着更多事情發生,我將繼續更新。

Update2:經過大量的搜索和調試後,我終於在運行應用程序的同時,通過瀏覽器提供的js幫助捕獲了錯誤消息的來源。該錯誤嘗試將shinyURL與DT和fileInput結合使用。我的猜測是shinyURL試圖保存一個url,這對於瀏覽器來說太長了,並且提供了用戶給出的信息。換句話說,它可能試圖用url info ..保存fileInput數據。我將shinyURL函數添加到上面的示例中,以便它將提供完全相同的錯誤消息,我被卡住了。我不需要立即解決問題,但我很好奇真正發生了什麼。 (產生錯誤線條突出了###的上方和下方。

+0

你可以做一個小的[重複的例子(http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example )?例如,與此討論相關的是'fileInput',還是任何數據集都可用於測試(請選擇一個)?如果這是我可以複製/粘貼到單個文件中的東西(例如使用'shinyApp'),將會有所幫助。最後,請包含顯式代碼以包含您正在使用的非基本包(即'library(shiny)','library(shinydashboard)')。 – r2evans

+0

是的。我很抱歉。我一直在努力提供正確的細節層次,因爲這是涉及超過4000行代碼的應用程序的一小部分。文件輸入似乎是問題的根源。 (我會在上面發佈可重複的示例) 顯示'Shiny App/data'中給出的數據框不會給出任何錯誤。 – creutzml

+0

很高興知道,謝謝。你有沒有試過把'browser()'放在你的每個(大)''反應式塊中,看看問題出在哪裏? (順便說一下:你可以使用'validate(需要(!is.null(userData()),FALSE))'並且多次測試'is.null(...)'。 '更多信息。) – r2evans

回答

1

解決方案

預計將在我最新的更新問題,用戶上傳文件的組合和數據幀中的相互作用DT導致由shinyURL生成的URL過長。

要找到允許shinyURL仍然在應用程序中的工作,我做了一些調查並發現DT輸出創建了自己的輸入對象,如input$tableId_rows_current,它試圖在用戶每次與之交互時保存表格的所有索引。因此,只要da ta框架太大,與它的任何交互都會傳遞一個url查詢錯誤,該錯誤在R Studio的控制檯上顯示爲ERROR [on_request_read] parse error

幸運的是,shinyURL也有忽略用戶選擇的輸入的固有方式。怎麼樣?只需簡單地放置一個「。」在創建新小部件時在輸入ID的開頭。或者,在DT表格輸出的情況下,在數據表輸出ID的開頭放置一個句點,以便忽略所有固有的DT輸入。

代碼解決方案:

ui <- dashboardPage(

    dashboardHeader(title = "Test") , 

    dashboardSidebar(
    sidebarMenu(
     menuItem("Selections", tabName = "selections"), 
     menuItem("Data Table", tabName = "dataTable") 
    ) 
), 

    dashboardBody(
    tabItems(
     tabItem(
     tabName = "selections", 
     selectInput("mapChoice", 
        label = "Choose a map:", 
        choices = c("", 
           "New Map from Data Table"), 
        selected = ""), 

     conditionalPanel("input.mapChoice == 'New Map from Data Table'", 
######################################################### 
# Add in a period before file input ID 
######################################################### 
      fileInput(".userData", 
        label = "Choose CSV File", 
        accept=c('text/csv', 
          'text/comma-separated-values,text/plain', 
          '.csv')),    

      uiOutput("newMapUI") 
     ), 
     # # Bookmark widget 
     shinyURL.ui(width = "400px") 
    ), 

     tabItem(
     tabName = "dataTable", 
######################################################## 
# Add in a period before data table output ID 
######################################################## 
     DT::dataTableOutput(".table") 
    ) 
    ) 
) 


) 


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

    # # Add in function for saving and recording urls as bookmarks 
    shinyURL.server(session) 

    userData <- reactive({ 

    path <- input$.userData 

    if (is.null(path)) 
     return (NULL) 

    results <- read.csv(file = path$datapath, 
         header = TRUE, 
         stringsAsFactors = FALSE) 
    results 

    }) 

    output$newMapUI <- renderUI({ 


    list(

     # Specify the column for labeling 
     if (!is.null(userData())) { 
     selectizeInput("nameCol", 
         label = "Choose the column to be used for 
         point labels: ", 
         choices = c(names(userData())), 
         multiple = TRUE, 
         options = list(placeholder = 'Name', 
             maxItems = 1)) 
     }, 

     # Specify longitude column 
     if (!is.null(userData())) { 
     selectizeInput("lonCol", 
         label = "Choose the column containing longitude 
         values: ", 
         choices = c(names(userData())), 
         multiple = TRUE, 
         options = list(placeholder = 'Longitude', 
             maxItems = 1)) 
     }, 
     # Specify latitude column 
     if (!is.null(userData())) { 
     selectizeInput("latCol", 
         label = "Choose the column conatining latitude 
         values: ", 
         choices = c(names(userData())), 
         multiple = TRUE, 
         options = list(placeholder = 'Latitude', 
             maxItems = 1)) 
     } 

    ) 



    }) 

    nameCol <- reactive({ 
    as.character(input$nameCol) 
    }) 

    lonCol <- reactive({ 
    as.character(input$lonCol) 
    }) 

    latCol <- reactive({ 
    as.character(input$latCol) 
    }) 



    newUserData <- reactive({ 

    if (is.null(userData())) 
     return (NULL) 

    # Create the new data frame: 
    if (length(nameCol()) != 0 && 
     length(lonCol()) != 0 && 
     length(latCol()) != 0) { 

     userData <- userData() 

     name <- nameCol() 
     lonCol <- lonCol() 
     latCol <- latCol() 

     results <- data.frame(Name = userData[, name], 
          Longitude = userData[, lonCol], 
          Latitude = userData[, latCol]) 

     results$Name <- as.character(results$Name) 
     results$Longitude <- as.numeric(results$Longitude) 
     results$Latitude <- as.numeric(results$Latitude) 

    } 

    results 

    }) 

    mapData <- reactive({ 

    data <- data.frame() 

    if (input$mapChoice == "New Map from Data Table") { 

     if (length(nameCol()) != 0 && 
      length(lonCol()) != 0 && 
      length(latCol() != 0)) { 
     data <- newUserData() 
     } 
    } 
     data 
    }) 

    output$.table <- DT::renderDataTable({ 

    datatable(mapData(), 
       extensions = c('Buttons', 'FixedHeader', 'Scroller'), 
       options = list(dom = 'Bfrtip', 
          buttons = list('copy', 'print', 
              list(extend = 'csv', 
               filename = 'map data', 
               text = 'Download') 
          ), 
          scrollX = TRUE, 
          pageLength = nrow(mapData()), 
          fixedHeader = TRUE, 
          deferRender = FALSE, 
          scrollY = 400, 
          scroller = FALSE, 
          autowidth = TRUE 
      ) 
    ) 

    } 
) # End of table render 

    } 

shinyApp(ui = ui, server = server)