Cryptic error message from trying to plot dataframe calculated in scripts

I am updating my post earlier because I've been finding solutions as I learn Shiny but I am still getting an error. I hope this is not bad form in this forum.
My app reads an R script containing a function, and reads a second script with an observer executing the function with data entered by the user (a dataframe from the HD and a numeric input). I learnt today that when reading the second R scipt with observeEvent I need to take the dataframe output out of the observer so I made the dataframe a reactive and that solved the problems I was having in my last reply to my early post. Now I get no errors from ggplot.
But now I get an error that seems to be something different, still related to the dataframe but apparently not from ggplot.
To give a reprex I will reproduce my original post with the new app code:

# Create toy data and save it in the HD
intab  <- data.frame(this=c(rep("A",3),rep("B",3)),
                     that=rep(1:3,2),
                     now=runif(6,2,8),
                     then=runif(6,3,9))
write.csv(intab,"intab.csv",row.names=FALSE)
# First script, saved as stuff1.R
stuff1 <- function(x,p) 
  {
  y <- x^p
  z <- log(y)
  return(z)
  }
# Second script, saved as stuff2.R
Datastuff$now2  <- stuff1(x=Datastuff$now,p=Powerstuff)
Datastuff$then2 <- stuff1(x=Datastuff$then,p=Powerstuff)
outtab2         <- data.frame(when=c(rep("now2",6),rep("then2",6)),
                              it=paste(rep(Datastuff$this,2),rep(Datastuff$that,2),sep="-"),
                              out=round(c(Datastuff$now2,Datastuff$then2),3))
# The app.R code
library(shiny)
library(ggplot2)
source("Stuff1.R")
#
ui <- fluidPage(titlePanel(list(tags$head(tags$style(".span2 {background-color: black;}")),
                           "CapCarga: Bioenergetic carrying capacity for mussel open sea cultivation")),
      sidebarLayout
      (
       sidebarPanel
        (fileInput(inputId="Datastuff",label="Choose stuff data file",accept=".csv"),
         numericInput(inputId="Powerstuff",label="Enter the power stuff",value=NULL), 
         actionButton("runScript","Run", icon("paper-plane"),style="color: #fff; background-color: #337ab7; border-color: #2e6da4")),
      mainPanel
       (plotOutput(outputId="plot",width="100%"))))
server <- function(input,output,session) 
  {
   datalist <- reactiveVal()
   restab   <- reactiveValues(outtab2=NULL)
   observe({
            req(input$Datastuff,input$Powerstuff)
            datalist(list(Datastuff=input$Datastuff,
                          Powerstuff=input$Powerstuff))
           })
   observeEvent(input$runScript,{
                                 source("Stuff2.R",local=list2env(datalist()))
                                 restab$outtab2 <- outtab2
                                })
   output$plot <- renderPlot({
                              req(input$Datastuff,input$Powerstuff,input$runScript)
                              p1 <- ggplot(data=restab$outtab2,
                                           aes(x=factor(restab$outtab2$it),
                                               y=restab$outtab2$out,
                                               fill=restab$outtab2$when))
                              p1 +  geom_bar(stat="identity",position=position_dodge(0.9)) +
                              labs(x="it",y="out",cex=0.5) +
                              ggtitle("now and then") +
                              scale_fill_discrete(name="it") +
                              theme(axis.text.x=element_text(angle=90))
                             })
}
shinyApp(ui=ui,server=server)

Thanks for any help.
Ruben

you constuct datalist() directly from the two raw values returned by fileInput Datastuff and numericInput Powerstuff.
However, you treat Datastuff (the fileInput) as though it is a dataframe, when its only a path to where a local copy of the csv has been made for you to access. You still need to read this into R as a csv.

The fileInput help for shiny shows an example for this. see read.csv(file$datapath,


ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE)
    ),
    mainPanel(
      tableOutput("contents")
    )
  )
)

server <- function(input, output) {
  output$contents <- renderTable({
    file <- input$file1
    ext <- tools::file_ext(file$datapath)

    req(file)
    validate(need(ext == "csv", "Please upload a csv file"))

    read.csv(file$datapath, header = input$header)
  })
}

shinyApp(ui, server)

Thanks nir, I adapted the example in ?fileInput to my case but I get the same error:

Warning: Error in $<-.data.frame: replacement has 0 rows, data has 1
1: runApp

I suspect this file reading need to be done somewhere else, no inside renderPlot(), perhaps inside observeEvent, when I try to execute the second script, Stuff2.R.

My app now is;

library(shiny)
library(ggplot2)
source("Stuff1.R")

ui <- fluidPage(titlePanel(list(tags$head(tags$style(".span2 {background-color: black;}")),
"CapCarga: Bioenergetic carrying capacity for mussel open sea cultivation")),
sidebarLayout
(
sidebarPanel
(fileInput(inputId="Datastuff",label="Choose stuff data file",accept=".csv"),
checkboxInput("header","Header",TRUE),
numericInput(inputId="Powerstuff",label="Enter the power stuff",value=NULL),
actionButton("runScript","Run", icon("paper-plane"),style="color: #fff; background-color: #337ab7; border-color: #2e6da4")),
mainPanel
(plotOutput(outputId="plot",width="100%"))))
server <- function(input,output,session)
{
datalist <- reactiveVal()
restab <- reactiveValues(outtab2=NULL)
observe({
req(input$Datastuff,input$Powerstuff)
datalist(list(Datastuff=input$Datastuff,
Powerstuff=input$Powerstuff))
})
observeEvent(input$runScript,{
source("Stuff2.R",local=list2env(datalist()))
restab$outtab2 <- outtab2
})
output$plot <- renderPlot({
file <- input$Datastuff
ext <- tools::file_ext(file$datapath)
req(input$Powerstuff,input$runScript,file)
validate(need(ext=="csv","Please upload a csv file"))
read.csv(file$datapath,header=input$header)
p1 <- ggplot(data=restab$outtab2,
aes(x=factor(restab$outtab2$it),
y=restab$outtab2$out,
fill=restab$outtab2$when))
p1 + geom_bar(stat="identity",position=position_dodge(0.9)) +
labs(x="it",y="out",cex=0.5) +
ggtitle("now and then") +
scale_fill_discrete(name="it") +
theme(axis.text.x=element_text(angle=90))
})
}
shinyApp(ui=ui,server=server)

I would modify your server code like this:

server <- function(input,output,session) 
{
  datalist <- reactiveVal()
  restab   <- reactiveValues(outtab2=NULL)
  justthedata <- reactive({
    read.csv(req(input$Datastuff)$datapath)
  })
  observe({
    req(justthedata(),input$Powerstuff)
    datalist(list(Datastuff=justthedata(),
                  Powerstuff=input$Powerstuff))
  })
  observeEvent(input$runScript,{
    s1 <- source("Stuff2.R",local=list2env(datalist()))
    restab$outtab2 <- s1$value
  })
  output$plot <- renderPlot({
    req(input$Datastuff,input$Powerstuff,input$runScript)
    p1 <- ggplot(data=restab$outtab2,
                 aes(x=factor(restab$outtab2$it),
                     y=restab$outtab2$out,
                     fill=restab$outtab2$when))
    p1 +  geom_bar(stat="identity",position=position_dodge(0.9)) +
      labs(x="it",y="out",cex=0.5) +
      ggtitle("now and then") +
      scale_fill_discrete(name="it") +
      theme(axis.text.x=element_text(angle=90))
  })
}

And I'd accept your modifying my server code like that because it works now.
I'm going to adapt the toy app to the real app now.
Thanks for explaining my errors. I learnt.
Highly appreciated.
Ruben

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.