Structure Server Function in a Shiny App - r

I am struggling with my first shiny app and having problems to make it work due to, I think, I am missing out something in the server function.
I have a R script that has two variables (the two reactive values in shiny) that creates a plot (a histogram) and a csv file with two columns (time and mm).
library(ggplot2)
**Pdmm** <- 125 # numeric input in shiny
**IndiceTorrencial** <- 10 # slider between 8 and 12 in shiny
DuracionAgua <- 24
IntervaloMin <- 60
IntervaloTiempo <- IntervaloMin/60
Intervalos <- DuracionAgua/IntervaloTiempo
t <- seq(1,Intervalos,IntervaloTiempo)
DF <- data.frame(t)
DF$I <- (**Pdmm**/24)*(**IndiceTorrencial**)^(((28^0.1)-(DF$t^0.1))/((28^0.1)-1)) # equation where the reactive values are running
DF$Pacu <- DF$t*DF$I
DF$Pmm <- c(DF$Pacu[1], diff(DF$Pacu, lag = 1))
DF$mm <- c(DF$Pmm[23],DF$Pmm[21],DF$Pmm[19],DF$Pmm[17], DF$Pmm[15],DF$Pmm[13],DF$Pmm[11],DF$Pmm[9],DF$Pmm[7],DF$Pmm[5],DF$Pmm[3],DF$Pmm[1],DF$Pmm[2],DF$Pmm[4],DF$Pmm[6],DF$Pmm[8],DF$Pmm[10],DF$Pmm[12],DF$Pmm[14],DF$Pmm[16],DF$Pmm[18],DF$Pmm[20],DF$Pmm[22],DF$Pmm[24])
ggplot(DF,aes(x=t,y=mm)) + geom_bar(stat = "identity",fill = "dodgerblue",color = "black") + scale_x_continuous(name = "t(h)", breaks = seq(1,24,1)) + scale_y_continuous(name = "mm")
My shiny app has, in its UI, a slider, a numeric input and a plot. It works, I will have time to make something better.
ui <- basicPage(
sliderInput(inputId = "coefTo",
label = h3("Torrentiality Coefficient"),
value = 10, min = 8, max = 12),
numericInput(inputId = "PmmS",
label = h3("Areal Precipitation"),
value = 100),
imageOutput("plot")
)
The problem is in the server function. I think I am sure that I have to use a reactive function in order to execute the code and to yield the results (histogram and csv). Also, to plot the histogram, I have a renderPlot.
server <- function(input, output, session){
data <- reactive({
DuracionAgua <- 24
IntervaloMin <- 60
IntervaloTiempo <- IntervaloMin/60
Intervalos <- DuracionAgua/IntervaloTiempo
t <- seq(1,Intervalos,IntervaloTiempo)
DF <- data.frame(t)
DF$I <- (input$PmmS/24)*(input$coefTo)^(((28^0.1)-(DF$t^0.1))/((28^0.1)-1))
DF$Pacu <- DF$t*DF$I
DF$Pmm <- c(DF$Pacu[1], diff(DF$Pacu, lag = 1))
DF$mm <- c(DF$Pmm[23],DF$Pmm[21],DF$Pmm[19],DF$Pmm[17], DF$Pmm[15],DF$Pmm[13],DF$Pmm[11],DF$Pmm[9],DF$Pmm[7],DF$Pmm[5],DF$Pmm[3],DF$Pmm[1],DF$Pmm[2],DF$Pmm[4],DF$Pmm[6],DF$Pmm[8],DF$Pmm[10],DF$Pmm[12],DF$Pmm[14],DF$Pmm[16],DF$Pmm[18],DF$Pmm[20],DF$Pmm[22],DF$Pmm[24])
DFm <- DF$mm
return(DFm)
})
output$plot <- renderPlot({
ggplot(data(DFm),aes(x=t,y=mm)) + geom_bar(stat = "identity",fill = "dodgerblue",color = "black") + scale_x_continuous(name = "t(h)", breaks = seq(1,24,1)) + scale_y_continuous(name = "mm")
})
}
When I run this script, I get the shiny app I have the slider and the numeric input, but not the plot getting an error message saying Error: unused argument (DFm). DFm is not created, so I assume that I am placing bad the code from my original script inside the shiny app, but I cannot figure out how to do it.
I have tried several things to make the server works, but I think that the script never runs inside the shiny app. I tried to create two reactive functions, one per each reactive value. I tried to put all the code from my original script out of the shiny leaving just the reactive values inside the shiny code... I tried with observe function as well.
Another problem I have is that I am not sure about the renderPlot. I am aware that I have to call the reactive function, data, but as I am not sure if it is well made.
I think that my server function is a total disaster. I have looked for examples in the shiny gallery and in Google, but I do not see something similar to help me.
Could anyone give a tip in order to fix my server function?
Many thanks in advance.

Following the advice of our colleague, I could solve my problem by setting DF, the first data frame I created, in return() inside the reactive function. Another confusion was how to set the object from the reactive function inside the renderplot.

Related

R Shiny application: Modifying plot without re-rendering it

I've been looking into ways to update a plot within an R Shiny application without having to re-render the whole plot. I'm working with temporal data which is animated via a Slider Input (animationOptions(playButton = TRUE)). The idea is to somehow highlight the part of the plot which is selected via the Slider Input. Re-rendering the whole plot at every animation step would make the whole application uselessly slow.
The most elegant solution with ggplot2 would have been, if shiny offered a way to add layers to the ggplot (e.g. + geom line()) and integrated this layer seamlessly into the plot without re-rendering it. Sadly, this does not seem to work. A bit of a hack could include creating a second ggplot-instance with exactly the same x/y-dimensions and overlapping the two plots.
EDIT:
I've just learnt that there are more javascript oriented plotting methods than ggplot2. For example, using dygraphs and adding a layer of dyShading, the selected area gets highlighted nicely. The basic question remains the same though, since changing the start- and end values of dyShading() seems to require re-rendering the whole plot.
library(shiny)
library(dygraphs)
library(xts)
data <- data.frame(
datetime = as.POSIXct("2016-06-20 17:00:00", tz = "UTC") + 1:100*60,
y = rnorm(100)
)
data_xts <- as.xts(data[,-1], data[,1])
minDatetime <- min(data$datetime)
maxDatetime <- max(data$datetime)
minY = min(data$y)
maxY = max(data$y)
plotlimits <- lims(x = c(minDatetime, maxDatetime), y = c(minY, maxY))
ui <- fluidPage(
sliderInput("timeslider", "Time Slider",
min = minDatetime,
max = maxDatetime,
value = c(minDatetime, minDatetime+10*60),
animate = animationOptions(interval=200)
),
dygraphOutput("dyplot")
)
server <- function(input, output) {
data_fil <- reactive({
data[data$datetime <= input$timeslider[2] & data$datetime >= input$timeslider[1],]
})
output$dyplot <- renderDygraph({
dygraph(data_xts) %>%
dyShading(
from = as.character(input$timeslider[1]),
to = as.character(input$timeslider[2]),
color = "tomato")
})
}
shinyApp(ui = ui, server = server)

Visualizing faceted data using interactive plotting in shiny

I'm having some trouble creating interactive plots in shiny that facet my data.
Here's some code that shows what I want, but it uses ggplot2 which is not interactive.
library(shiny)
library(data.table)
library(ggplot2)
x <- 1:10000
dt <- data.frame(a = 1:100, b = sample(x,100,replace=T), c = sample(x,100,replace=T), d = sample(x,100,replace=T))
dt.molten <- melt(dt,id.vars="a")
ui <- fluidPage(
plotOutput("gplot")
)
server = function(input, output) {
output$gplot <- renderPlot({
ggplot(y.molten,aes(x = value)) +
geom_histogram(binwidth = 100000) +
facet_wrap( ~ variable,ncol = 1)
})
}
shinyApp(ui = ui, server = server)
In my actual app, the amount of facets varies, so I can't simply hard code in 3 separate plots using highcharter, ggvis,or plotly.
Ideally I'd like it to look something like this:
require(highcharter)
x <- stl(log(AirPassengers), "per")
hchart(x)
Except with histograms instead of time-series data.
The main issue is that the data i'm plotting stretches over like -3,000,000 to +3,000,000 with a high concentration around 0. This makes it hard to see the bars at the edges, so I'd like for users to be able to zoom into certain ranges of the plot without having to select it via some ui element.
I'm open to suggestions using any plotting method in R, although i'd like to stay away from rCharts.
EDIT: I did discover that using plotly::ggplotly almost achieved what I'm looking for, however it isn't very clean. I did g <- ggplot(*plot code*) then ggplotly(g). Works decent, but it'll take quite a bit of work to clean up I think.

Removing the X,Y in nearPoints() Output

I want to use the functionality of nearPoints() to print out summary statistics for a specific point without printing the x, y associated with that point. I have been able to use this function printing the data frame and variations of the data frame. Is there anyway to suppress those columns
to customize the output? nearPoints comes from the latest version of shiny 0.12.1 but I believe may have been introduced a little earlier.
I know the documentation says this:
Note that these functions are only appropriate if the x and y variables are present in the data frame, without any transformation. If, for example, you have a plot where a the x position is calculated from a column of data, then these functions won’t work. In such a case, it may be useful to first calculate a new column and store it in the data frame.
but wanted to know if there was any kind of work around.
Here is the app that illustrates this problem, note that I'm using all of those libraries in my bigger app:
library(shiny)
library(ggplot2)
library(Cairo)
library(plyr)
library(dplyr)
library(shinydashboard)
library(grid)
library(gridExtra) # also loads grid
library(grDevices)
library(ggmap)
library(sqldf)
cars <- mtcars
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
dataTableOutput("info")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(cars, aes(x=cyl, y=carb)) + geom_point()
})
output$info <- renderDataTable({
summary_cars <- ddply(cars, .(gear, cyl, carb),
function(dd){as.data.frame(cbind(Mean_hp = mean(dd$hp),
Mean_wt = mean(dd$wt))
)
})
#This works-------------------------------------------------------
# nearPoints(summary_cars, input$plot_click, threshold = 10,
# addDist = TRUE)
#Removing the columns does not work ---------
nearPoints(select(summary_cars,-cyl,-carb), input$plot_click, threshold = 10,
addDist = F)
})
}
shinyApp(ui, server)

Create a number of renderPlot functions, based on the number of plots I have in a list of ggplots?

Is there any way I can dynamically create a number of renderPlot functions, based on the number of plots I have in a list of ggplots?
I have a Shiny app where instead of having a stable UI, and instead of using renderUI, I am relying on a user-supplied config file to tell Shiny how many plots to show. The config file also supplies data and pretty much helps do most of the heavy lifting.
After much battling, I'm mostly there. With the handy-dandy config file, I can build the correct UI, and generate the correct number of ggplots. The ggplots live in a list, creatively named list_of_ggplots.
But now, I'm at a point where I have a list of ggplots, and I need to allow them to be plotted by using them like this:
output$plot1 <- renderPlot({
print(list_of_ggplots[[1]])
})
But now I have an existentialist crisis -- I can't do it like this, since the user-supplied config file tells me how many plots I have. I can no longer hard code the renderPlot call like is usually done in Shiny, since the number of these functions needed is defined in the config file.
Given my list of ggplots, I need some way to generate the renderPlot calls.
Has anyone done this or have any ideas? Much appreciated.
Here's my code:
SERVER.R:
library(shiny)
library(ggplot2)
# 3 simple plots of different colors -- used here instead of all the complicated stuff
# where someone uses the config file that specified 3 plots, with data, etc.
ggplot_names <- c("p1", "p2", "p3")
ggplot_colors <- c("red", "blue", "green")
list_of_ggplots <- list()
j = 1
for (i in ggplot_names){
i <- ggplot(data.frame(x = c(-3, 3)))
i <- i + aes(x)
i <- i + stat_function(fun = dnorm, colour=ggplot_colors[[j]])
list_of_ggplots[[j]] <- i
j <- j+ 1
}
## here's the problem -- the user specified 3 plots.
## I can't hardcode the following shinyServer functions!!!
## What if tomorrow, the user specifies 2 plots instead?
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
print(list_of_ggplots[[1]])
})
output$plot2 <- renderPlot({
print(list_of_ggplots[[2]])
})
output$plot3 <- renderPlot({
print(list_of_ggplots[[3]])
})
})
UI.R
## this top part is actually sourced from the config file
## since Shiny needs to know how many tabPages to use,
## names for the tabs, etc
number_of_tabPages <- 3
tab_names <- c("", "Tab1", "Tab2", "Tab3")
tabs<-list()
tabs[[1]]=""
for (i in 2:(number_of_tabPages+1)){
tabs[[i]]=tabPanel(tab_names[i],plotOutput(paste0("plot",i-1)))}
## Here's the familiar UI part
shinyUI(fluidRow(
column(12,
"",
do.call(navbarPage,tabs)
)
)
)
You can use this solution (I modified only the shinyServer part of your scripts, so I don't list the repeating code here):
shinyServer(function(input, output) {
observe(
lapply(seq(3),function(i) output[[paste0("plot",i)]] <- renderPlot(list_of_ggplots[[i]]))
)
})
Of course, you can replace 3 by a variable.

Many error signs when running ggplot in render plot (shiny in general)

Took very basic shiny scripts and were able to play around the generic data sets. When I tried to put in my own and run ggplot, I've come across several errors. Most recent is what appears in my main panel of shiny app and console in Rstudio
...
"ggplot2 doesn't know how to deal with data of class reactive"
...
In general, I stripped down my ggplot to the most basic elements and still not sure from where ggplot is calling data while in shiny. I am guessing the reactive function, but honestly, I am lost.
Below are scripts
_____ui.R________
shinyUI(pageWithSidebar(
headerPanel('Mock Risk Scorecard'),
sidebarPanel(
selectInput('xcol', 'X Axis', names(RandomRiskCard)),
selectInput('ycol', 'Y Axis', names(RandomRiskCard),
selected=names(RandomRiskCard)[[2]]),
min = 1, max = 9),
mainPanel(
plotOutput('plot1')
)
)
)
_____server.R____
palette(c("#E41A1C", "#377EB8"))
shinyServer(function(input, output, session) {
# Combine the selected variables into a new data frame
selectedData <- reactive({
RandomRiskCard[, c(RandomRiskCard$xcol, RandomRiskCard$ycol)]
})
output$plot1 <- renderPlot({
p <- ggplot(selectedData, aes(x = RandomRiskCard$xcol, y = RandomRiskCard$ycol))
p <- p + geom_point()
})
})
I also loaded up my data and Run Shiny in different script windows as follow
install.packages("shiny")
library(shiny)
library(ggplot2)
runApp("U:/App-1")
as well as
RandomRiskCard = read.csv("U:/App-1/RandomRiskCard.csv")
I am eventually hoping to incorporate factor function and annotate with colors like I had done with my original ggplot. If it wasn't already obvious I am a newbie at this, but shiny has me completely twisted.
Reactive expressions should be called in the same way as parameter-less functions, with following parentheses: ggplot(selectedData(),...
xcol and ycol should be obtained via input:
p <- ggplot(selectedData(), aes(x = input$xcol, y = input$ycol)) in output$plot, and
RandomRiskCard[, c(input$xcol, input$ycol)] in selectedData

Resources