Cannot populate drop down menu dynamically in R shiny - r

I am trying to create an APP using R Shiny. I want to upload data (.csv file). Then I want to populate the column names in CSV file in a drop down menu. I am unable to do that.
Please refer to the codes below :
---- server.r -----
library(shiny)
options(shiny.maxRequestSize = 32*1024^2)
shinyServer(
function(input, output){
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath,head=TRUE,sep=",")
})
output$sum <- renderTable({
if(is.null(data())){return ()}
summary(data())
})
output$table <- renderTable({
if(is.null(data())){return ()}
data()
})
# the following renderUI is used to dynamically generate the tabsets when the file is loaded. Until the file is loaded, app will not show the tabset.
output$tb <- renderUI({
if(is.null(data()))
h5("no file loaded")
else
tabsetPanel(tabPanel("Data", tableOutput("table")),tabPanel("Summary", tableOutput("sum")))
})
output$col <- renderUI({
selectInput("phenomena", "Select the Phenomena", names(data))
})
})
----- ui.R -----
library(shiny)
shinyUI(fluidPage(
titlePanel("Hotspot Analysis of EnviroCar Data"),
sidebarLayout(
sidebarPanel(
# uploading the file
fileInput("file","Upload *.csv file"), # fileinput() function is used to get the file upload contorl option
uiOutput("col")
),
mainPanel( uiOutput("tb") )
)
))

I guess the problem is in server.R:
selectInput("phenomena", "Select the Phenomena", names(data))
Here, you're using data without parentheses so what you actually obtain is the source code of the function data, and names(data) is NULL. I think all you need is to replace names(data) by names(data()).

Related

Why does this Shiny App not display dataframe using RStudio?

I have a list of data frames, ls_df, comprising two dataframes from the datasets package.
I am trying to load these two dataframes into a Shiny app using the code below. However, it does not work, with the error message no item called "ls_df" on the search list being returned. Does anyone know how to fix?
ls_df <- list(datasets::airmiles,
datasets::AirPassengers)
ui <- fluidPage(
selectInput("ls_df", label = "Dataset", choices = ls("ls_df")),
verbatimTextOutput("summary"),
tableOutput("table")
)
server <- function(input, output, session) {
output$summary <- renderPrint({
dataset <- get(input$ls_df, "ls_df")
summary(dataset)
})
output$table <- renderTable({
dataset <- get(input$ls_df, "ls_df")
dataset
})
}
shinyApp(ui, server)
The list needs the names:
library(shiny)
ls_df <- list(airmiles=datasets::airmiles,AirPassengers=datasets::AirPassengers)
ui <- fluidPage(
selectInput("ls_df", label = "Dataset", choices = names(ls_df)),
verbatimTextOutput("summary"),
tableOutput("table")
)
server <- function(input, output, session) {
output$summary <- renderPrint({
dataset <- ls_df[[input$ls_df]]
summary(dataset)
})
output$table <- renderTable({
dataset <- ls_df[[input$ls_df]]
dataset
})
}
shinyApp(ui, server)
Two things wrong:
Your list needs names, as discussed in PorkChop's answer. If this were the only required change, then PorkChop's answer would suffice.
get(input$ls_df, "ls_df") is an error. This should be rather clear, though, since it prevents the shiny interface from starting. This error is because the envir= argument of ls and get require an object, not the character name of an object. (One could go "inception" and use ls(get("ls_df")) and similarly for get, but that hardly seems necessary or useful.)
ls_df <- list(airmiles=datasets::airmiles, # <-- named list
AirPassengers=datasets::AirPassengers)
ui <- fluidPage(
selectInput("ls_df", label = "Dataset", choices = ls(ls_df)), # <-- no quotes
verbatimTextOutput("summary"),
tableOutput("table")
)
server <- function(input, output, session) {
output$summary <- renderPrint({
dataset <- get(input$ls_df, ls_df) # <-- no quotes
summary(dataset)
})
output$table <- renderTable({
dataset <- get(input$ls_df, ls_df) # <-- no quotes
dataset
})
}

Resetting fileInput in Shiny App

I have been trying for a long time to reset fileInput in a Shiny app and read solutions to similar problems, but my problem still persists. Most solutions ultimately lead to using Dean Attali's brilliant shinyjs package and the reset() function therein. Here's what my code looks like after following these instructions:
library(shiny)
library(shinyjs)
library(xlsx)
library(tidyverse)
ui <- fluidPage(
useShinyjs(),
fileInput('inFile', 'Choose file'),
actionButton('reset', 'Reset'),
radioButtons("type","Choose file type",choices = c('csv','xls')),
tableOutput('tbl')
)
server <- function(input, output, session) {
rv <- reactiveValues(data = NULL)
observe({
req(input$inFile)
if(input$type=='csv'){
rv$data <- read.csv(input$inFile$datapath)
}
if(input$type=='xls'){
rv$data <- read_excel(input$inFile$datapath)
}
})
observeEvent(input$reset, {
rv$data <- NULL
reset('inFile')
})
output$tbl <- renderTable({
rv$data
})
}
shinyApp(ui, server)
I initially select the csv option and am able to load a csv file. Now when I press the reset button, it clears the data. As soon as I select the xls option, I get an error:
Listening on http://127.0.0.1:4135
Warning: Error in : Unknown file extension: csv
Which makes me believe that input$inFile$datapath still contains the pathname of the csv file that I selected earlier. I have run out of ideas on how to solve this problem and would greatly appreciate some help please.
Ideally fileInput would properly reset, but you can do this as a workaround. Add an explicit flag variable (rv$clear) to indicate whether you're in cleared state, and toggle that on and off in high-priority observers when reset and upload occur, respectively.
library(shiny)
library(shinyjs)
library(xlsx)
library(tidyverse)
ui <- fluidPage(
useShinyjs(),
fileInput('inFile', 'Choose file'),
actionButton('reset', 'Reset'),
radioButtons("type","Choose file type",choices = c('csv','xls')),
tableOutput('tbl')
)
server <- function(input, output, session) {
rv <- reactiveValues(
data = NULL,
clear = FALSE
)
observe({
req(input$inFile)
req(!rv$clear)
if(input$type=='csv'){
rv$data <- read.csv(input$inFile$datapath)
}
if(input$type=='xls'){
rv$data <- read_excel(input$inFile$datapath)
}
})
observeEvent(input$inFile, {
rv$clear <- FALSE
}, priority = 1000)
observeEvent(input$reset, {
rv$data <- NULL
rv$clear <- TRUE
reset('inFile')
}, priority = 1000)
output$tbl <- renderTable({
rv$data
})
}
shinyApp(ui, server)

Getting state of a country from lat lon for a database in shiny using R

From the lat and lon in the input csv file, I have to get the state in which the point lies for the entire data, I have tried the revgeocode function for dataframe separately in R, it is working, but when I included it in shiny it is not working and showing the error "object of type 'closure' is not subsettable". Can someone help me out with this.....
Code:
library(shiny)
#layout of the page
ui <- fluidPage(
# Application title
titlePanel("Hotspot Analysis"),
sidebarLayout(
#panel for getting input
sidebarPanel(
#for getting input from user
fileInput('datafile', 'Choose CSV file',
accept=c('text/csv', 'text/comma-separated-values,text/plain')),
#The action button prevents an action firing before we're ready
actionButton("vis_rep", "Get Visual Representation")
),
#panel for displaying output
mainPanel(
dataTableOutput('filetable')
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# Get the upload file
filedata <- reactive({
infile <- input$datafile
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
read.csv(infile$datapath)
})
filedata$textaddress <- reactive({
mapply(FUN = function(lon, lat) revgeocode(c(lon, lat)), filedata$Longitude, filedata$Latitude)})
filedata$state <- reactive({
sapply(strsplit(as.character(filedata$textAddress),','),"[",3)})
observeEvent(input$vis_rep,{
output$filetable <- renderDataTable({
filedata()
})
})
}
# Run the application
shinyApp(ui = ui, server = server)

shiny fileinput r dataframe

Using R shiny, I am developing a simple app that allows user to input data from a file. With csv or txt files everything works fine, but I can not make R dataframes to load.
## SERVER.R
shinyServer(function(input, output) {
infile <- reactive({
infile <- input$datafile
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
infile<load(input$datafile$datapath)
})
myData <- reactive({
df<-infile()
if (is.null(df)) return(NULL)
})
output$value1 <- renderPrint({
names(iris)
})
output$value2 <- renderPrint({
names(myData())
})
load("iris.Rdata") ## data loaded for testing
})
## UI.R
shinyUI(fluidPage(
fileInput("datafile", label = h3("File input")),
fluidRow(column(4, verbatimTextOutput("value1"))),
fluidRow(column(4, verbatimTextOutput("value2")))
))
When I run this app I can see the names of the iris dataset loaded only for testing, but respect the names of the loaded file (which should be rendered as value2) only shows "NULL"
Any help?? thanks in advance!
I think this is what you want. You had a couple of typos, and you probably didn't quite understand what load actually does, it loads a set of objects into memory.
I did the following things:
added some initialization code to save a couple of .Rdata for testing, they both have exactly one object in them, a dataframe. The code needs this.
add a line to parse out the first object in that loaded datafile and return it
Here is the code:
server.r
## SERVER.R
#Initialization
library(datasets)
save(iris,file="iris.Rdata")
save(mtcars,file="m.Rdata")
shinyServer(function(input, output) {
infile <- reactive({
infile <- input$datafile
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
objectsLoaded <- load(input$datafile$name)
# the above returns a char vector with names of objects loaded
df <- eval(parse(text=objectsLoaded[1]))
# the above finds the first object and returns it
return(df)
})
myData <- reactive({
df<-infile()
if (is.null(df)) return(NULL)
return(df)
})
output$value1 <- renderPrint({
names(iris)
})
output$value2 <- renderPrint({
names(myData())
})
load("iris.Rdata") ## data loaded for testing
})
ui.r
## UI.R
shinyUI(fluidPage(
fileInput("datafile", label = h3("File input")),
fluidRow(column(4, verbatimTextOutput("value1"))),
fluidRow(column(4, verbatimTextOutput("value2")))
))
Here is the output:

Dynamic Input Selector Based on Uploaded Data

Thanks in advance for your help. I understand how to manipulate dynamic inputs based off of other inputs for pre-defined datasets.
i.e. Load a car dataset. User selects Radio button to say they only want to look at blue cars. This changes the options in some Input Selector on the UI.
However, if I want to allow a user to upload a csv file, how do I dynamically update all of the relevant widgets.
i.e. User uploads their data, an Input Selector displays all variables in the dataset for plots and regressions.
The italicized part is my trouble.
ui.r
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
titlePanel("My R Shiny App"),
sidebarPanel(
fileInput('file', 'Choose file to upload.'),
#Select Box: y
selectInput("y_input", label = h5("Select Time Series/Response Variable"),
choices = names(myData),
selected = NULL)
)
)
)
server.r
library(shiny)
#Run once when app is launched
#Load data
shinyServer(function(input, output) {
#Run once each time a user visits the app
#Put code to build a distinct set of reactive objects for user
output$Variable_Selector <- renderUI({
if(is.null(input$file))
return(NULL)
inFile <- input$file
myData <- read.csv(inFile$datapath)
if (is.null(myData))
return(NULL)
})
})
global.r
myData = NULL
Thanks!
Here's one solution using the functions observe and updateSelectInput - with some other minor modifications to your code. To demonstrate I made the following two csv files with different column names:
Df1 <- data.frame(
x=1:5,
y=2*(1:5),
z=3*(1:5))
##
Df2 <- data.frame(
a=6:10,
b=2*(6:10),
c=3*(6:10),
d=letters[1:5],
stringsAsFactors=F)
##
write.csv(Df1,file="~/tempfiles/Df1.csv",row.names=F)
##
write.csv(Df2,file="~/tempfiles/Df2.csv",row.names=F)
ui.R:
library(shiny)
shinyUI(fluidPage(
titlePanel("My R Shiny App"),
sidebarPanel(
fileInput(
'file',
'Choose file to upload.'
),
selectInput(
"y_input",
label = h5("Select Time Series/Response Variable"),
""
)
)
))
server.R:
library(shiny)
shinyServer(function(input, output, session) {
inFile <- reactive({
if (is.null(input$file)) {
return(NULL)
} else {
input$file
}
})
myData <- reactive({
if (is.null(inFile())) {
return(NULL)
} else {
read.csv(inFile()$datapath)
}
})
observe({
updateSelectInput(
session,
"y_input",
choices=names(myData()))
})
})
global.R:
myData <- NULL
And here are a couple of screenshots showing how the UI changes based on the uploaded file:

Resources