Reputation: 313
So I'm creating an R shiny app where I need to upload a few files and operate on them to output some (let's say 3) plots. So in every renderPlot() function in server I need to repeat the operations for it to work (code is chunky now). I was wondering if there's any way to assign the ingested file and operations to a global variable and access it in every renderplot() function? Is there a way to actually access it outside the server() at all (I've been told no)?
In other threads, I was told to use reactive() or reactiveValues() but to no avail. Below is the sample code:
sample2 <- as.data.frame(matrix(rnorm(10*100, 1, .5), ncol=10))
write.csv(sample, "sample.csv") #Creating sample csv to be ingested in R shiny
ui <- fluidPage(
headerPanel("Webpapp"),
sidebarPanel(
fileInput(inputId = "filedata", #Upload sample.csv here
label = "Upload the Raw Data File",
accept = c("text/csv", "text/comma-separated-values,text/plain",
".csv")),
selectInput("title", "Select title:", choices = list("hi", "hello"), selected = "Hi"),
),
mainPanel(plotOutput('plot')),
mainPanel(plotOutput('normalized_plot')),
mainPanel(plotOutput('advanced_normalized_plot'))
)
server <- function(session, input, output) { #original code I have needs session
data <- reactive({
req(input$filedata)
read.csv(input$filedata$datapath, header = T)
})
normalized <- reactive({
#I want to assign these objects as a global variable which can be use by other output functions
df <- data()
normalizd_df <- df + 1.5
colnames(normalizd_df) <- paste(input$title,rep(1:10)) #I do need to use input in this reactive function
advanced_normalized <- normalized_df * 15.454
})
output$plot <- renderPlot({
#This works but I do not want to do this every output function
sample_d <- data()
plot(density(sample_d[,1]), main = input$title)
})
output$normalized_plot <- renderPlot({ #Does not work
plot(density(normalized$normalizd_df[,1]), main = input$title)
})
output$advanced_normalized_plot <- renderPlot({
sample_a <- advanced_normalized - normalized_df #This doesn't work
plot(density(normalized$advanced_normalized[,1]), main = input$title)
})
}
shinyApp(ui = ui, server = server)
Upvotes: 0
Views: 1264
Reputation: 504
If you really want to assign something to global, you can use the <<-
operator. Or assign("x", value = data, envir = .GlobalEnv)
.
But, you really don't want to. It's almost never, ever a good idea. Especially since you need to make use of reactive inputs.
If sample_d <- data()
is too many keystrokes, just ignore assigning within the local environment (the output
object) and use data()
.
output$plot <- renderPlot({
plot(density(data()[,1]), main = input$title)
})
If you want an object with multiple values, a list of objects, make your reactive object into a list and reference with $
Be sure to note however, your reactive object is a function call. So if the reactive object is data
and we want the list item normalized_df
we would call the reactive object data()
with ()
and then index into the list that function returns with $
. So all together we would have data()$normalized_df
.
data <- reactive({
req(input$filedata)
d <- read.csv(input$filedata$datapath, header = T)
list(data = d,
normalized_df = d + 1.5,
advanced_normalized = df + 1.5 * 45.454)
})
output$normalized_plot <- renderPlot({ #Does not work
plot(density(data()$normalizd_df[,1]), main = input$title)
})
output$advanced_normalized_plot <- renderPlot({
plot(density(data()$advanced_normalized[,1]), main = input$title)
})
Below is a minimal example that shows this in action:
library(shiny)
ui <- fluidPage(
titlePanel("Old Faithful Geyser Data"),
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 10,
value = 2)
),
mainPanel(
column(6, verbatimTextOutput("console1")),
column(6, verbatimTextOutput("console2"))
)
)
)
server <- function(input, output) {
data1 <- reactive({
datum <- mtcars
d1 <- mtcars[1:input$bins]
d2 <- d1 + 1
d3 <- d1 * 1.5
list(d1, d2, d3)
})
data2 <- reactive({
datum <- mtcars
list(d1 = mtcars[1:input$bins],
d2 = mtcars[1:input$bins] + 1,
d3 = mtcars[1:input$bins] * 1.5)
})
output$console1 <- renderPrint({
data1()
})
output$console2 <- renderPrint({
data2()
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 1