Shiny app fileInput, getting variables from within that file

Hello all,

I am using fileInput() to read a csv file into a variable. I would then like to do calculations on that csv file, such as length() of a column or adding the columns together. This is very simple if it were just a data.frame within the R environment, but I cannot figure it out within shiny.

My question is, once you read a csv in as a variable, how do you access the columns within to do things with? I have watched multiple tutorials and read many blogs, but everything I have found shows how to display the data--not how to first do math and then display data. Does anyone have any links or examples?

Here is an example of what I would like to do.

This was edited from an example from Abhinav Agrawal on GitHunGist:

An example .csv would look like this code:

df = data.frame(matrix(c(80, 60, 50, 40, 50, 55), nrow=3, ncol=2))
colnames(df) <- c("ht_inches", "wt_lbs")

library(shiny)

ui <- fluidPage(
titlePanel("File Input"),
sidebarLayout(
sidebarPanel(
fileInput("file","Upload the file"),
tags$hr(),
checkboxInput(inputId = 'header', label = 'Header', value = TRUE),
checkboxInput(inputId = "stringAsFactors", "stringAsFactors", FALSE)
),
mainPanel(
uiOutput("tb")
)

)
)

server <- function(input,output){
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath, sep=",", header = input$header, stringsAsFactors = input$stringAsFactors)
})

output$filedf <- renderTable({
if(is.null(data())){return ()}
input$file
})

output$sum <- renderTable({
if(is.null(data())){return ()}
summary(data())

})

output$table <- renderTable({
if(is.null(data())){return ()}
data()
})

output$tb <- renderUI({
tabsetPanel(tabPanel("About file", tableOutput("filedf")),tabPanel("Data", tableOutput("table")),tabPanel("Summary", tableOutput("sum")))
})
}

shinyApp(ui, server)

What I would like to do is read in the table and create variables based on the csv called height and weight. Then create an output of BMI = weight/(height^2)

Thank you for the help!

1 Like

Just use a reactive expression to hold the data.

Here's an example, but you have to have the cars.csv file somewhere in your computer (or change the variable names and logic to whatever makes sense for your data).

[If you want to download the cars dataset for this example, you can do write.csv(cars, file = "cars.csv", row.names = FALSE) and that will create a cars.csv file wherever your working directory is (if you're not sure, run getwd() at the console)]

library(shiny)
library(dplyr)

ui <- fluidPage(
  fileInput("csvFile", "Drag cars.csv over here!"),
  tableOutput("rawData"),
  tableOutput("modifiedData")
)

server <- function(input, output, session) {
  rawData <- eventReactive(input$csvFile, {
    read.csv(input$csvFile$datapath)
  })
  
  output$rawData <- renderTable({
    rawData() %>% head
  })
  
  output$modifiedData <- renderTable({
    rawData() %>% mutate(sum = speed + dist) %>% head
  })
}

shinyApp(ui, server)
1 Like

Hello Barbara,

Wow--thank you so much!! This is exactly what I was looking for, you are amazing.

I noticed you used the column names speed and dist to specify the variables to be summed, but what if you did not know the column names? I attempted to use "sum = rawData[ ,1] + rawData[ ,2]" in place of speed and dist, but did not work.

Is there a way to have the code be more generic in how it pulls the column, i.e. I know which column it will be, just not what the user necessarily will name it (dist or distance)?

Thank you!

Here's a way to do that with dplyr (it will sum the 1st and 2nd columns, so you need to make sure that's a valid operation -- e.g. need to make sure they're both numeric):

library(shiny)
library(dplyr)

ui <- fluidPage(
  fileInput("csvFile", "Drag cars.csv over here!"),
  tableOutput("rawData"),
  tableOutput("modifiedData")
)

server <- function(input, output, session) {
  rawData <- eventReactive(input$csvFile, {
    read.csv(input$csvFile$datapath)
  })
  
  output$rawData <- renderTable({
    rawData() %>% head
  })
  
  output$modifiedData <- renderTable({
    vars <- names(rawData())
    rawData() %>% 
      mutate(sum = .data[[vars[[1]]]] + .data[[vars[[2]]]]) %>% 
      head
  })
}

shinyApp(ui, server)

Hi barbara,

Thanks for these examples, I found them really helpful also.

I'm working on a similar problem: import a file and do calculations, but with a selectInput option as well. Would you be able to expand your second example to include a selectInput() option also?

For example, in the modifiedData the user could choose either 1) sum the 1st and 2nd columns, or 2) sum the 2nd and 3rd columns.