Dataframe from 2 R scripts not found in server to make plot

Dear Shiny experts, I think you will fild my error quickly. I am new to Shiny and have been developing my app for a few days and I am close but currently stuck with an error that shows in the main panel: Error: object 'outtab2' not found. The real app will load 3 data files, input a few numeric constants, and then run two R scripts to show a plot made with ggplot. When I press Run App in RStudio the error message appears. Here is a toy code and app that has the same structure as the real code and app but it is reduced to the bare minimum, it is a reprex as requested in the rules of this community:

Start reprex.

#Create toy data and save it to 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)

R script that contains one function (the real script has many functions but the output is one data.frame as in this case).

Save it as 'Stuff01.R'

stuff1 <- function(x,p)
{
y <- x^p
z <- log(y)
return(z)
}

This is the second script, simply executing the stuff1 function with data. Save it 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))

And finally this is the app:

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()
observe(
{
datalist(
list(
Datastuff=input$Datastuff,
Powerstuff=input$Powerstuff
)
)
}
)
observeEvent(
input$runScript,{
source("Stuff2.R",local=list2env(datalist()))
}
)
output$plot <- renderPlot({
#browser()
p1 <- ggplot(data=outtab2,aes(x=factor(it),y=out,fill=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") +
geom_text(aes(label=out),colour="black",size=3,nudge_x=0) +
theme(axis.text.x=element_text(angle=90))
})
}
shinyApp(ui=ui,server=server)

End of reprex.

I've checked that the R part works fine, from data to plot. I think my problem is that I haven't found the way to make the renderPlot function WAIT for input so when I load the app it tries to find the data.frame output that should be coming from execution of the R scripts.

Thanks in advance for your help.

Ruben

I managed to solve the “object not found error” by using req() on two places. So my app now loads correctly and waits for input. BUT at the point of entry of the last input , it once again crashes because of the “object not found error”. So it seems that I need a last item to tell the app not to run the Run button until it is pressed by the user.

Having the same data file in the HD and the two R scripts, the app is now

#Start of reprex

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()
observe({req(input$Datastuff,input$Pwerstuff)
datalist(list(Datastuff=input$Datastuff,Powerstuff=input$Powerstuff))})
observeEvent(input$runScript,{source("Stuff2.R",local=list2env(datalist()))})
output$plot <- renderPlot({
req(input$Datastuff,input$Pwerstuff)
p1 <- ggplot(data=outtab2,aes(x=factor(it),y=out,fill=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") +
geom_text(aes(label=out),colour="black",size=3,nudge_x=0) +
theme(axis.text.x=element_text(angle=90))})
}
shinyApp(ui=ui,server=server)

#End of reprex
Any help will be highly appreciated.
Ruben

Ok, keeping conversing with myself, I also solved the latest problem with my app by adding the input$runScript to the req() function inside render plot. So now my app as shown above but with the first line inside renderPlot as
req(input$Datastuff,input$Powerstuff,input$runScript)
will work as expected, as you can see running my reprex, but after entering the data file and the numeric input and then pressing the Run button, will give me the following error:

Warning: Error in ggplot: object 'outtab2' not found
169: ggplot
168: renderPlot [...\Reprex/app.R#48]
166: func
126: drawPlot
112: reactive:plotObj
96: drawReactive
83: renderFunc
82: output$plot
1: shiny::runApp
Warning: Error in $<-.data.frame: replacement has 0 rows, data has 1
1: shiny::runApp

Here I am lost. Why renderPlot doesn't find outtab2 given that I have passed the necessary input data and pressed the Run button thus executing script Stuff2.R which produces outtab2?

Hope someone can spot my error and point out what I am missing here. Thanks.

Ruben