3

I just wanted to upload a shapefile and a raster in a RShiny app and then execute a script. What I have wrote is the following;

library(shiny)
library(raster)
library(rgdal)
ui=shinyUI(fluidPage(pageWithSidebar(
  headerPanel("Header1"),
  sidebarPanel(
   fileInput('layer', 'Choose Layer', multiple=FALSE, accept='tif'),
   fileInput('shapefile', 'Input Shapefile/AOI',accept=c('.shp','.dbf','.sbn','.sbx','.shx',".prj"), multiple=TRUE)

  mainPanel(
    plotOutput("mapPlot")
  )
)))


server = shinyServer(function(input,output){

  inFile <- reactive({input$layer})
  data <- brick(inFile())
  inFile2 <- reactive({input$shp})
  data2 <- readOGR(inFile2())

  output$mapPlot<-renderPlot({plot(data)
    plot(data2, add=T)})
})
shinyApp(ui = ui, server = server)

What I am getting is the following error

Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.) Stack trace (innermost first):

45: .getReactiveEnvironment()$currentContext 44: .dependents$register 43: inFile 42: brick 41: server [~/.active-rstudio-document#18] 5: 4: do.call 3: print.shiny.appobj 2: print 1: source

I have no idea what I did wrong and I can't find a source that explains how to solve this. Can anyone help me debug it or even help me understand what I did wrong?

2
+50

Your code has several structural problems with the reactives and so on, and some possible more fundamental problems with shapefile.

Here's a working version with some caveats that follow:

ui=shinyUI(fluidPage(pageWithSidebar(
  headerPanel("Header1"),
  sidebarPanel(
      fileInput('layer', 'Choose Layer', multiple=FALSE, accept='asc'),
      fileInput('shape', 'Choose gml', multiple=FALSE, accept="gml")

  ),
  mainPanel(
      plotOutput("mapPlot")
  )
)))


server = shinyServer(function(input,output){

    inFile <- reactive({
        raster::brick(input$layer$datapath)
    })

    inShp = reactive({
        readOGR(input$shape$datapath)
    })

    output$mapPlot<-renderPlot(
    {
        plot(inFile());
        plot(inShp(), add=TRUE)
    })
})

Note that everything in the server function is either in a "reactive" or a "renderer". That's what was causing your initial problem.

Secondly the file upload input returns a data frame with a datapath column which is where the file has been dropped. So in your code you would have been trying to read from input$layer which is a dataframe of upload data rather than input$layer$datapath which is the column with the file name you want.

Thirdly it is hard to make shapefiles work with shiny uploads. Shapefiles must have a .shp and a .shx component for readOGR to work, and possibly a .dbf and .prj component too. You can upload several files in a shiny upload widget (is that why you have multiple=T?) but the server renames them so that the data frame of input$shape contains the names 0.shp, 1.shx, 2.dbf and so on. It might be possibly to rename these back together, but most shapefile upload solutions require users to upload a ZIP file of everything which is then extracted by the server.

My solution above, and in order to show how the reactive stuff works which was your first problem, is to load a GML file instead of a shapefile. In my test code I did writeOGR(pts, "pts.gml","pts", driver="GML") just to get something I could upload to shiny and plot over a raster.

  • Since the day I uploaded my code I made a few changes, like fileInput('shapefile', 'Input Shapefile/AOI',accept=c('.shp','.dbf','.sbn','.sbx','.shx',".prj"), multiple=TRUE) (see changes) but nevertheless it was great getting help from that – George Nostradamos Mar 14 '18 at 12:07
  • but nevertheless it was great getting help. I'll try using .gml. But after plotting my data, as I said, I would like to call a script using source() and then create plots based on the outputs of that R script. How can I do that? – George Nostradamos Mar 14 '18 at 12:14
  • ^ That's very general and a big ask. I would put that in a separate question with what you have tried. – GISKid Mar 14 '18 at 13:01
  • I think you might be able to work with uploaded shapefile components by renaming the uploaded parts so they have a common name and the right extensions. But that's a whole other problem from what was causing your error message which was the placing of code outside reactives and renderers. – Spacedman Mar 14 '18 at 16:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.