I am trying to create a Shiny App.
I'd like it to download a CSV file from the web and store it on the local machine, then perform analysis.
My current approach is:
ui.R
library(shiny)
shinyUI(pageWithSidebar(
# Application title
headerPanel("TEST"),
sidebarPanel(
sliderInput("range", "Date Range:",
min = 0, max = 15, value = c(0,15))
),
# Show a tabset that includes a plot, summary, and table view
# of the generated distribution
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("plot"))
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
datasetInput <- function(){
x1 <- strptime(Sys.time(), "%Y-%m-%d %H:%M:%S")
x2 <- strptime(file.info("/srv/shiny-server/Data/current.csv")$mtime, "%Y-%m-%d %H:%M:%S")
if ( difftime(x1, x2, units='mins') > 20 ){
str <- "wget http://www.web.com/file.csv -O /srv/shiny-server/Data/current.csv"
system(str)
}
data <- read.csv("/srv/shiny-server/Data/current.csv")
return(data)
}
output$plot <- renderPlot({
data <- datasetInput()
plot(data)
})
So, everything works. The data plots perfectly. The problem is the wget script doesn't get called. Regardless of where I put it.
For simplicity my main goal is to download and save a CSV file when the app runs. Then read in that CSV file as my main dataframe.
The ultimate goal is for my app to do the time check (Check if file is older then 20 minutes) every time someone does anything with the app. If it is older, I want to download/save the file, and update my data frame.
* note * using the wget function is a work around for a problem accessing a password protected CSV file.
The problem/solution is discussed here:
R Import - CSV file from password protected URL - in .BAT file
I don't know much about how Shiny works, the code used to generate the Shiny app is mostly from:
http://rstudio.github.io/shiny/tutorial/#tabsets
Try using the httr package instead of a raw wget. Here's an example of a Shiny application that also downloads a remote CSV file and parses it. https://github.com/trestletech/dallas-police/blob/master/shiny/server.R
Also you may find this tutorial valuable, as I think you could be using reactiveFunctions as the sources of your data input.
Related
Sorry for what seems like a basic question, I'm very new to R and programming in general. I want to be able to determine what file type was picked from a file. For example, in this code I need to have two separate buttons for importing a CSV or excel file:
observeEvent(input$CSV, {
Table <- read.table(file.choose(), header=TRUE, sep=",")
output$ImportedTable <- DT::renderDataTable(Table)
})
observeEvent(input$Excel, {
Table <- read_excel(file.choose())
output$ImportedTable <- DT::renderDataTable(Table)
})
(input$Excel/CSV is the output of an actionButton in the main pannel)
Ideally, I'd like to only require one button instead of two, and have the program able to determine what file type was chosen, and import it accordingly. and ideally, I'd like to be able to sort what data types are available to choose from when importing, since currently it allows the user to pick all file types, instead of just ones in a table format. I'd appreciate any help, thanks!
You seem to work with shiny (this is an important bit of information missing from your main post).
In shiny you can use fileInput to restrict the format of input files. Here is a minimal reproducible example.
library(shiny)
ui <- fluidPage(
fileInput(inputId = "file_csv", label = "CSV file", accept = ".csv"),
fileInput(inputId = "file_xlsx", label = "XLSX file", accept = ".xlsx"),
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
Note that you can see the effect of accept when opening the app in your browser of choice. RStudio's native app window or Viewer Pane does not seem to respect the accept argument.
I am relatively new to programming/R/Shiny. I have a network of R scripts that take in data, transform it, and produce figures that are output to a PDF. I have been using this for some time now. I now need to transfer that process to a Shiny app.
This has been problematic because none of the variables that are present in one script can be used in another.
Is there a "simple" way to make these variables accessible between R scripts ? That would be a much, much simpler solution than trying to transfer the entirety of the code into the app.r file. Any help would be much appreciated. Thanks.
Example code - Here, I would like the user to upload a CSV file and then press a button that runs an R script that modifies and adds to the data, creating two new dataframes. Those two dataframes would then be used in "report.R" to create PDF reports.
library(shiny)
ui <- fluidPage(
fileInput('upload', 'Choose file to upload',
accept ='.csv'
),
actionButton('analyze', 'Analyze the data')
)
server <- function(input, output, session) {
data <- reactive({
req(input$upload)
read.csv <- vroom(input$file$datapath)
})
observeEvent(input$analyze, {
source("analyze.R")
#this transforms data from the csv and produces new dataframes based on the original, call them df1 and df2. df1 and df2 are then used as data in reports generated by:
source("report.R")
}
)
}
shinyApp(ui, server)
I've been making an app in shiny, and it is meant to use/edit the same file for multiple different people.
The idea is that when you open the app for the first time, it'll prompt you to select the file, and save the location of the file so you don't have to select it every time you open the program.
I can't seem to find a way to do this, only saving edits to the file. Is there a way, or would you just have to select the file every time?
EDIT: here is some simple code to give you an idea of what i've been working with
library(shiny)
setwd("~/myfiles")
ui <- fluidPage(
fileInput("user_file", "Please enter a file"),
textOutput("txt_param")
)
server <- function(input, output, session) {
file_path <- input$user_file$datapath
output$txt_param <- renderText(as.character(input$user_file$datapath))
### Store the file's path in a csv to access later ###
as.data.frame(file_path)
write.csv(file_path, "user_file_path.csv")
}
shinyApp(ui, server)
I parse an uploaded XML file in the renderPlot function of the server.R script of R-Shiny
output$oscar <- renderPlot({
doc <- xmlParse("www/Human_body_front_and_side.svg.eps.xml")
#load the XML as a picture
body<-readPicture(saveXML(doc))
#plot it
grid.arrange(pictureGrob(body), ncol=1)
})
but I get the following error for the parsing:
XML content does not seem to be XML
I had loaded the correct libraries (shiny, XML), and checked that the uploaded xml file is fine.
The interesting point is that if, before starting the "runApp" of R-Shiny, I do in the R terminal:
doc <<- xmlParse("Human_body_front_and_side.svg.eps.xml")
no error and everything works fine. So it looks like R shiny has an issue with parsing xml. I am a newbie in R-Shiny, hence does anyone see what it needs to recognize that XML file?
ui.R:
library(shiny)
shinyUI(fluidPage(
titlePanel("Human body"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
plotOutput("humanBody")
)
)
))
server.R
library(shiny)
library(XML)
library(grImport)
library(gridExtra)
# Define server logic to draw a histogram
shinyServer(function(input, output){
output$humanBody <- renderPlot({
doc <- readPicture("./www/Human_body_front_and_side.svg.eps.xml")
grid.arrange(pictureGrob(doc), ncol=1)
})
})
If the goal is to plot the human body from the xml, this code works. Parsing the xml is not necessary since since the readPicture() function expects an XML which your file already is. Let me know if this helps.
I'm new to Shiny and am trying to run an app using data from an excel file. Seems like it should be simple, but can't figure it out. there's load of info out there on more complex tasks (uploading files interactively, where you specify columns, file location etc) - but all I want is an app that uses data from a single excel file that has loaded in the background.
Similar questions have been asked before (Uploading csv file to shinyApps.io and R Shiny read csv file) but I didn't get a satistactory answer from them.
I have my excel file saved in the same directory as the app.R file, in a folder named 'data'. And I read it into the server part of my script like this:
server <- function(input, output){
# Read in data
myDF <- read_excel('data/MyShinyData.xlsx')
When I run the app.R file to test the app, it works fine. But when I publish it to the Shiny website using shinyapps::deployApp('pathToWorkingDirectory') I get a grayed out version of the app that has no interactivity. The app also publishes to the website fine if I simulate the data within the app.R file (the excel file is just this simulated data, written to excel with write.xlsx) - its only when I take out the code for simulating the data and replace it with the read_excel command that it stops working. I've also tried with a .csv file instead of .xlsx, but same problem.
I've copied the full code from the app.R file below.
What am I doing wrong? Thanks for your help.
library('ggplot2')
library('shiny')
library('psych')
library('readxl')
#===============
#This code makes a histogram, a coplot, and a prediction for species richness ('SpNat') given Forest cover ('NBT').
#===============
m1 <- lm(SpNat ~ NBT, data=myDF) #For prediction. best to create all non-reactive [ie non-updating] code outside the app, so it doesn't have to run every time.
#==========
# ui section
#==========
ui <- fluidPage(
### MAKING A TITLE
titlePanel("Dashboard based on excel data"),
### DIVIDING INPUTS TO SIDEBAR VS MAIN PANELS:
sidebarLayout(
sidebarPanel( #everything nested in here will go in sidebar
#dropdown input for coplot:
tags$h3('Select coplot variables'), #heading
selectInput(inputId='choiceX', label='Choose X variable',
choices=c('Species richness'='SpNat', 'Forest cover'='NBT', 'Pest control'='PC')), #***Choices are concatenated text strings.
selectInput(inputId='choiceY', label='Choose Y variable',
choices=c('Species richness'='SpNat', 'Forest cover'='NBT', 'Pest control'='PC')),
selectInput(inputId='choiceZ', label='Choose conditioning variable',
choices=c('Species richness'='SpNat', 'Forest cover'='NBT', 'Pest control'='PC')),
#checkbox input for pairs plots:
tags$h3('Select variables for pairs plots'), #heading
checkboxGroupInput(inputId='vars', label='Choose at least two variables for pairs plot',
selected=c('SpNat', 'NBT', 'PC'), #'determines which vars start off checked. Important for pairs, cos <2 and plot wont work.
choices=c('Species richness'='SpNat', 'Forest cover'='NBT', 'Pest control'='PC')), #***Server receives input as a single concatenated text
#slider input for prediction:
tags$h3('Predicting forest cover'), #heading
sliderInput(inputId='num',label='Pick a forest cover level', value=10, min=1, max=100)),
mainPanel( #everything nested in here will go in main panel
#specify output for app, including headings:
tags$h3('Coplot:'),
plotOutput(outputId='coplot'),
tags$h3('Histogram:'),
plotOutput(outputId='pairs'),
tags$h3('Predicted species richness:'),
verbatimTextOutput('prediction'))))
#==========
# server section
#==========
server <- function(input, output){
# Read in data
myDF <- read_excel('data/MyShinyData.xlsx') #don't need full path
myDF$PC <- as.factor(myDF$PC)
myDF <- select(myDF, SpNat, NBT, PC)
#create output object, and name it so it corresponds to the ui output function ID, plus use the ui input ID to create it:
output$coplot <- renderPlot(
ggplot(myDF, aes_string(input$choiceX, input$choiceY, col=input$choiceZ)) + geom_point()) #note use of aes_string to allow inputID use direct.
output$pairs <- renderPlot({
pairs.panels(subset(myDF, select=input$vars))})
output$prediction <- renderPrint({
newData <- data.frame(NBT=input$num)
cat(predict(m1, newdata = newData))
})
}
#==========
# and stitch together
#==========
shinyApp(ui=ui, server=server)
Figured it out. I had two problems:
(1) I had copied the app into a new folder prior to publishing, so the working directory had changed - needed to reset to the folder containing my app.R file prior to running shinyapps::deployApp.
(2) a couple of packages required by my app load automatically into my R console (I've made changes to my .Rprofile file). So while I didn't need to load these to run the app locally, I did to publish it online.
Both pretty dumb mistakes, but you live and learn.