2016-08-18 74 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)