Using column names in csv file in drop-down box and use data in analysis

First time posting ...
I had a beautiful shiny until changed from explicitly reading in the csv file to using the fileInput and want to use the column names in the input for the selectInput. Now I get errors that the data is not found. Tried two reactives to get my df2 and df3, but selectInput does not recognize these.

Goal: user selects and uploads file (df), user chooses the stock (colnames in df3), and then the analysis is performed over df2 and df3.

ui <- fluidPage(
                titlePanel("Analysis of Returns Data"),
                fileInput("file1", "Choose CSV file", multiple = FALSE,
                          accept = c("text/csv","text/comma-separated-values,text/plain",".csv"),
                          width = NULL, buttonLabel = "Browse...",
                          placeholder = "No file selected"),
                selectInput("series", "Choose a stock ticker:", choices=c()),
                plotOutput("time",width="63%",height="275px"),
                
                mainPanel(
                  tabsetPanel(
                    tabPanel("Histogram",plotOutput("hist",height="275px"),
                             sliderInput(inputId="num",label="Choose the number of bins",
                                        value=25,min=5,max=35)),
                    
                    tabPanel("Boxplot", plotOutput("box",height="275px"),
                             radioButtons(inputId="rad","Extent of whiskers. Whiskers to:",selected="1",
                                          choiceNames=list(" extremes",
                                               " 1 x interquartile range",
                                               " 2 x interquartile rate"),
                                          choiceValues=list(0,1,2),inline=TRUE)),
                    
                    tabPanel("Volatility",plotOutput("vol",height="275px"),
                         sliderInput(inputId="num2",label="Choose size of the moving average window in months",
                                        value=30,min=10,max=120)),
                    
                    tabPanel("Summary", verbatimTextOutput("stats"))
                  )
                )
)
      
#################################################################################
#
# Server function
#
server <- function(session,input,output) {

  data1 <- reactive({
          validate(need(input$file1,""))
          inFile <- input$file1
          if (is.null(inFile))
          return(NULL)
          df <- read.csv(inFile$datapath,na.strings = c("", "NA", "#N/A"))
          df2 <- cast(df,date ~ TICKER, value='RET')
          return(df2)    
 })

  data2 <- reactive({
          df3 <- df2[,-1]
          updateSelectInput(session,"series",choices=colnames(df3))    
          return(df3)    
  })
  
  
# Create the plot of the chosen series 
#  
  output$time <- renderPlot({
    
    nr <- length(df2)
    acc <- array(data=NA,dim=nr,dimname=NULL)
    r <- array(data=NA,dim=nr,dimname=NULL)
    
    r <- df3[,input$series]
    
    w <- which(!is.na(r))
    xmin <- min(w)
    
    for (i in xmin:nr) {
      if (i == xmin){acc[i]=1}
      if (i > xmin) {acc[i]=acc[i-1]*(1 + r[i])}}
    
    rout <- data.frame(df2$date,acc)
    ggplot(data=df3, aes(x=df2$date,y=acc)) +
      geom_line(color="darkblue")+ labs(x="Month",y="Value of $1",title="Value of $1") +
      scale_y_continuous(labels=scales::dollar_format()) +
      theme(plot.title = element_text(hjust = 0.5,face="bold"))   })
 
# Create the histogram that allows the user to select the number of bins
#
  output$hist <- renderPlot({
    
    hist(df3[,input$series],col="lightblue",breaks=input$num,
                                  xlab="Series",main="Histogram of series",
                                  border="darkblue")})
#
# Create the statistics that will go on the last tabbed page
#          
  output$stats<- renderPrint({
    
    summary(df3[,input$series])})
#
# Create moving window standard deviation plot
#  
  output$vol <- renderPlot({
    
    rs <- df3[,input$series]
    dd <- df2$date
    n <- as.numeric(input$num2)
    m <- length(df2$date)
    nloops <- m-n
    s <- array(data=NA,dim=nloops,dimname=NULL)
    d <- as.Date(rep(NA,nloops))
    rr <- array(data=NA,dim=n,dimname=NULL)
   
    j <- 1
    for (k in 1:nloops){
      j=k
      for (i in 1:n) {
        rr[i] <- rs[j]              
        j <- j+1}
      
      s[k] <- sd(rr,na.rm=TRUE)                      
      d[k] <- dd[j]     
      }
 
    mwout <- data.frame(s,d,drop=F)
    
    ggplot(data=mwout, aes(x=d,y=s)) +
      geom_line(color="darkred")+ 
      labs(x="Month",y="Standard deviation",
           title="Moving window standard deviation") +
      theme(plot.title = element_text(hjust = 0.5,face="bold"))   
    })
  
#
# Convert the user selected boxplot attribute to a variable, rd
#
  observeEvent(input$rad,{     
          if(input$rad=="0") {rd=0}
          if(input$rad=="1") {rd=1}
          if(input$rad=="2") {rd=2}
 
  output$box <- renderPlot({
    
    boxplot( df3[,input$series],horizontal=TRUE,col="lightgreen",
                                     border="darkgreen",range=rd,
                                     xlab="Series",main="Boxplot of series")})
  }
  )
  
}  

################################################################################

shinyApp(ui=ui, server=server)

Sections like reactive() and renderPlot() are like functions, the variables you create inside them are not visible outside. So df2 assigned in data1 <- reactive() cannot be used in data2 <- reactive(). To do that you would need to make df2 a reactiveVal or a member of a reactiveValues. You've done this a lot. e.g. put this before data1, and you also need to change the format of the assignments further down.

df2 <- reactiveVal()
df3 <- reactiveVal()

Here is a simplified version of your app. I refer to df2 and df3 as data1() and data2() for the reason explained by woodward. I also use aes_string() inside of ggplot() so that the column name selected in the selectInput, which is returned as a string, can be used to set the y axis.

library(shiny)
library(ggplot2)
ui <- fluidPage(
  titlePanel("Analysis of Returns Data"),
  fileInput("file1", "Choose CSV file", multiple = FALSE,
            accept = c("text/csv","text/comma-separated-values,text/plain",".csv"),
            width = NULL, buttonLabel = "Browse...",
            placeholder = "No file selected"),
  selectInput("series", "Choose a stock ticker:", choices=c()),
  
  mainPanel(
  plotOutput("time",width="63%",height="275px")
   # tableOutput("TBL")
  )
)

#################################################################################
#
# Server function
#
server <- function(session,input,output) {
  
  data1 <- reactive({
    validate(need(input$file1,""))
    inFile <- input$file1
    if (is.null(inFile))
      return(NULL)
    df <- read.csv(inFile$datapath,na.strings = c("", "NA", "#N/A"))
    df2 <- head(df, 8)
    return(df2)    
  })
  
  data2 <- reactive({
    df3 <- data1()[,-1]
    updateSelectInput(session,"series",choices=colnames(df3))    
    return(df3)    
  })
  
   output$time <- renderPlot({
     ggplot(data=data2(), aes_string(x="Country",y=input$series)) + geom_point(color="darkblue")   
   })
 }
shinyApp(ui = ui, server = server)

Oh my gosh -- this worked! Once I saw in your response that the reference to the dataframes are now, for example, data1()[.input$series] instead of df2[,input$series], and so on, it works beautifully. I made changes throughout for the different tabs and graphs and it works well. Thank you!

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