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.
Related
I developed a shiny app which displays some dynamic charts. These charts are generated at execution time according to the value of some buttons. This shiny app gets the data from a raw csv which is previously treated and transformed. I got a Rscript apart from the shiny app to do all those "transformations" of the raw data. What I would like to do is to call this Rscript from the shiny app in order to be executed when the shiny app is launched.
I have already checked these links but it didn't help at all: How can I connect R Script with Shiny app in R? and this one using Source() in Shiny. I checked the Rstudio documentation too: http://shiny.rstudio.com/tutorial/lesson5/.
I think it should be something like this, being procesadoDatos.R the RScript. i just want the source command to be executed at the beginning in order to load the data as the shiny app is starting:
source("procesadoDatos.R",local = TRUE)
shinyServer(function(input, output,session) {
(renderplots, reactives elements and so on)}
The Rscript is the shiny project path as the server.R and UI.R files. I also tried including the path but it didn't work either.
Another thing I tried was to create a function which makes all the transformations and then call it from server.R file after sourcing it:
source("procesadoDatos.R",local = TRUE)
generate_data(ticketsByService_report10.csv)
Being generate_data this function defined in the RScript:
generate_data <- function(csv_file) {
(all those transformation, data frame an so on)}
In all cases I got the same error saying that the data frames which are generated in the RScript aren't found.
Does anyone know what is wrong? Thanks in adavance
Scoping in Shiny
All this largely depends on where exactly you call source(). If you need the data to be found from within both the UI and the server function, you put source() outside the app.
If you place source() inside the server function, the UI won't be able to find any object created by the script. If you put this inside a render function, the objects are only visible inside that render function. See also Scoping rules for Shiny
Note that if you have separate server.R and ui.R files and you want the UI to find the objects created by the script, you should add a global.R file to your app directory. The source() command then goes in the global.R file.
A small example:
source('testScript.R')
shinyApp(
fluidPage(
selectInput("cols", "pick columns",
choices = names(x)),
dataTableOutput("what")),
function(input, output, session){
output$what <- renderDataTable(x)
}
)
and testScript.R contains one line:
x <- iris
The key here is:
the script actually has to create these objects
the script should be sourced in the correct spot.
So if you can do the following:
shinyApp(
fluidPage(
selectInput("cols", "pick columns",
choices = names(x)),
dataTableOutput("what")),
function(input, output, session){
source('testScript.R', local = TRUE)
output$what <- renderDataTable(x)
}
)
you get an error about not being able to find x. That's normal, because x is now only defined inside the environment of the server function.
You still can do this though:
shinyApp(
fluidPage(
dataTableOutput("what")),
function(input, output, session){
source('R/testScript.R', local = TRUE)
output$what <- renderDataTable(x)
}
)
Note how x is only needed inside the server function, not inside the UI.
Using functions
For functions, the same thing applies. You put the function definition in a script and source it like before. A function is nothing else but an object, so the script essentially creates a function object that then can be found using the exact same scoping rules.
Keep in mind though that this function should return something if you want to use the result of the function. So put this trivial example in testScript.R:
myfun <- function(x){
tmp <- iris[x]
return(tmp)
}
And now you can do the following:
source('testScript.R', local = TRUE)
shinyApp(
fluidPage(
selectInput("cols", "pick columns",
choices = names(myfun())),
dataTableOutput("what")),
function(input, output, session){
output$what <- renderDataTable(myfun(input$cols))
}
)
This doesn't work any longer if you put the source() inside the server function. The UI side won't be able to see myfun() any more.
rm(list = ls())
shinyApp(
fluidPage(
selectInput("cols", "pick columns",
choices = names(myfun())),
dataTableOutput("what")),
function(input, output, session){
source('R/testScript.R', local = TRUE)
output$what <- renderDataTable(myfun(input$cols))
}
)
# Error in myfun() : could not find function "myfun"
I'm trying to get a Shiny reactive UI running. It is getting quite complex (in terms of lines of code) so I thought refactoring was a good idea. To put it short, this is my server code:
require(ggplot2)
require(h2o)
shinyServer(function(input, output, session) {
#stop()
localH2o <<- h2o.init(nthreads = 3) #Global variable
source("BuilderServer.R", local = TRUE)[1]
source("ReviewerServer.R", local = TRUE)[1]
# CleanupFUnctions
session$onSessionEnded(function() {
rm(list=ls())
})
})
where I assumed source with local = TRUE was just like copy-paste the content of the R files. So they contain functions of the form output$functionName <- renderUI({code}). The ui code depends on these functions, most of them are reactive, the ui code looks like this:
shinyUI(navbarPage("Metamodel",
tabPanel("Build Custom Model",
fluidRow(
column(12,align="center",
uiOutput("BuilderUpTitle")
)
),
fluidRow(
column(3,
uiOutput("BuilderAxisSelector")
)
)
)
))
In this particular case, the "BuilderUpTitle" function looks like this:
output$BuilderUpTitle <- renderUI({
inFile <- input$BuilderInputFile
if(is.null(input$BuilderInputFile)){
fileInput("BuilderInputFile", "Upload a xlsx file")
} else {
#R Stuff done here with the file
textInput("text", label = h3("Model Title"), value = "Enter text...")
}
})
I wrote the code yesterday and it was working. Today I turned on the computer again, and when launching the app, not even the dependencies from the server.R appear to load (ggplot2 and h2o). The download button from the "BuilderUpTitle" function doesn't appear at all and shiny appears to only execute the ui.R code. I set the workspace to the folder of the sourcefiles and it doesn't help. Even if I uncomment the stop() function from the server, nothing seems to change. Setting breakpoints in RStudio doesn't stop the code inside the server, so that is why I think shiny is not calling the server function. However, the code was working before and I did not modify a single file. I even copied the content of the source files to the server.R code and still they do not load. Is there something obvious that I'm missing? Thank you in advance!
Ok, once again, I found myself what the problem is, and none of the things I said would've made anyone find what was wrong. Here is the tiniest possible code that reproduces the problem:
ui.R
shinyUI(fluidPage(
fluidRow(
uiOutput("itWillLock"),
uiOutput("itWillLock")
)
))
server.R
shinyServer(function(input, output) {
output$itWillLock <- renderUI({
sliderInput("slider","Slider",min=0,max=1,value=0)
})
})
I guess R gets stuck in an infinite loop and never reaches the server.R file. Is this a bug that I should report? Or just common sense will keep people out of this trouble. Thank you!
I am very new to shiny and ran quite fast in a problem which impedes to continue my work. I created a .xlsx file and tried to load this within shiny.
A similar problem was dicussed here but was not finally solved.
I tried to keep the code as simple as possible:
library(shiny)
ui <- fluidPage(
fileInput("uploadFile", "XLSX file"),
verbatimTextOutput("summary")
)
server <- function(input, output) ({
dataset<-reactive({
inFile <- input$uploadFile
dat<-read.xlsx("inFile$datapath", 1)
return(dat)
})
output$summary <- renderText({summary(dataset())})
})
Just loading the .xlsx file in R works fine with this code:
read.xlsx("testdata.xlsx", 1)
Adding browser() after inFile <- input$uploadFile in serverand calling inFile gives I think the correct object which contains .$datapath.
The error I get after uploading the file is:
Error in loadWorkbook(file) : Cannot find inFile$datapath
I hope this is not to silly but I just can figure out how to solve it. What I would like to know is how can I store my uploaded file as a dataframe within shiny?
You should leave the "" from the dat<-read.xlsx("inFile$datapath", 1) line.
This one works:
dat<-read.xlsx(inFile$datapath, 1)
Best,
RĂ³bert
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.
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.