Calling variables from reactive functions inside render*() - r

I have a server.R file in the following form:
server.R
shinyServer(
function(input, output, session) {
mydata<- reactive({
df<- dataframe1
variable1
variable2
list(df, variable1, variable2)
})
output$plot<- renderPlot({
p<-ggplot(mydata()$df, aes(y=V8, x = 1:nrow(mydata()$df), fill = V8))
print(p)
})
})
My issue is that the call to ggplot, while it seems to recognize mydata$df(), it returns the error
Error in nrow(mydata()$df) : could not find function "mydata".
I am not sure where my syntax is wrong. Can anyone shed some light? Thanks!

To my knowledge, reactive shiny objects don't play well with lists. As it appears you aren't using 'variable1' and 'variable2' just omit them and just do the dataframe (which I assume has been made globally accessible and isn't imported?). It also could simply be calling the reactive before the ggplot call, but I err towards simplicity if not using those extra variables. A very quick example:
runApp(
list(ui = basicPage(
h1('Demo Shiny'),
plotOutput("plot")
)
,server = function(input, output) {
mydata <- reactive({
dataframe1 <- data.frame(cond = rep(c("A", "B"), each=10),
xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
dataframe1
})
output$plot = renderPlot({
df <- mydata()
p<-ggplot(df, aes(x=xvar, y = yvar)) + geom_point()
print(p)
})
})
)

I'm going to shamless steal most of #charles code, but i think the problem in this case is actually your aes(). This seems to work
runApp(
list(ui = basicPage(
h1('Demo Shiny'),
plotOutput("plot")
)
,server = function(input, output) {
mydata <- reactive({
df <- data.frame( V8=sample(1:4, 20, replace=T))
list(df=df, variable1=1, variable2=2)
})
output$plot = renderPlot({
p<-ggplot(mydata()$df, aes(x=seq_along(V8), y = V8)) + geom_point()
print(p)
})
})
)
The problem was referring to variables in your aes that were not in your data.frame that you passed to ggplot2. Here by making sure to include a proper variable from the df, we seem to be fine.

Related

Can not understand the ggplot histogram

I don't understand why my R code give me this error:
data must be a data frame, or other object coercible by fortify(), not a numeric vector.
library(shiny)
library(ggplot2)
ui <- fluidPage( sliderInput(inputId = "num",
label = "Choose a number",
value = 25, min = 1, max = 100), plotOutput("ggplot") )
server <- function(input, output) { output$ggplot <- renderPlot({
ggplot(data=rnorm(input$num), aes(input$num)) + geom_histogram() }) }
shinyApp(ui = ui, server = server)
The first argument to ggplot should be a data frame. You have supplied the output of rnorm(), which is a vector. That's the first problem.
The second is that aes() should refer to a column name in the supplied data frame.
I would create a data frame first using input$num. Something like this:
server <- function(input, output) {
data_df <- data.frame(x = rnorm(as.numeric(input$num)))
output$ggplot <- renderPlot({
ggplot(data = data_df, aes(x = x)) + geom_histogram()
})
}

Is it possible to read points from a ggplot stat_qq plot with NearPoints?

I'm building a shiny app and I'm trying to detect clicked points in a stat_qq plot with nearPoints. I'm struggling to get this code working, I always end up with the error message:
nearPoints: not able to automatically infer xvar from coordinfo.
I tried to specify xvar and yvar inside of the nearPoints function, however, for the qq-plot I only need to specify one variable. Whichever one I specify, the other one generates the error.
library(shiny)
library(ggplot2)
ui <- fluidPage(
mainPanel(
plotOutput("qqplot", click = "qqplot_click"),
verbatimTextOutput("excl")
)
)
server <- function(input, output, session) {
rdata <- data.frame(rnorm(200, 20, 2), rep(TRUE, 200))
names(rdata) <- c("data","Select")
output$qqplot <- renderPlot({ggplot(data=rdata, aes(sample=data)) + stat_qq() + stat_qq_line()
})
excl.data <- eventReactive(input$qqplot_click, {
res <- nearPoints(rdata, input$qqplot_click, yvar='data', allRows = TRUE)
xor(rdata$Select, res$selected_)
})
output$excl <- renderPrint(excl.data())
}
shinyApp(ui, server)
Does anyone have an idea what I am missing?
You have to use ggplot_build to get the rendered data.
server <- function(input, output, session) {
rdata <- data.frame(rnorm(200, 20, 2), rep(TRUE, 200))
names(rdata) <- c("data","Select")
gg <- ggplot(data=rdata, aes(sample=data)) + stat_qq() + stat_qq_line()
ggdata <- ggplot_build(gg)$data[[1]]
output$qqplot <- renderPlot({
gg
})
observe({
print(input$qqplot_click)
})
excl.data <- eventReactive(input$qqplot_click, {
res <- nearPoints(ggdata, input$qqplot_click,
xvar="theoretical", yvar="sample", allRows = TRUE)
xor(rdata$Select, res$selected_)
})
output$excl <- renderPrint(excl.data())
}

How to modularize a simple bar plot in Shiny?

This is my app code:
app.R
library(shiny)
source("func.R")
# create data
name <- c("Moller", "Mayer", "Bernard")
sales <- c(35000, 40000, 60000)
df <- data.frame(name, sales)
# app
server <- function(input, output, session) {
x <- callModule(testPlot, "test", data = reactive(df), xAxis = reactive("name"), yAxis = reactive("sales"))
}
ui <- fluidPage(
testPlotUI(id = "test", stringName = "test")
)
shinyApp(ui = ui, server = server)
And this is my module code:
func.R
library(shiny)
library(ggplot2)
testPlotUI <- function(id, stringName){
ns <- NS(id)
fluidRow(
column(12,
plotOutput(stringName)
)
)
}
testPlot <- function(data, xAxis, yAxis){
output$test <- renderPlot({
ggplot(data(), aes_string(x=xAxis(), y=yAxis())) + geom_bar(stat = "identity")
})
}
This code ends up with this error:
Error in module(childScope$input, childScope$output, childScope, ...)
: unused arguments (childScope$input, childScope$output,
childScope)
How can I make this work?
The reason you are getting that error is that it is essential that the first three arguments to the server part of the module be input, output and session. So you need to change:
testPlot <- function(data, xAxis, yAxis){
output$test <- renderPlot({
ggplot(data(), aes_string(x=xAxis(), y=yAxis())) + geom_bar(stat = "identity")
})
}
into:
testPlot <- function(input, output, session, data, xAxis, yAxis){
output$test <- renderPlot({
ggplot(data(), aes_string(x=xAxis(), y=yAxis())) + geom_bar(stat = "identity")
})
}
With that change alone, your code will now run without any errors. However, nothing will appear. That is because you forgot another key component of using modules, which is to wrap all input/output ids in the ns() function. So change:
column(12,
plotOutput(stringName)
)
into:
column(12,
plotOutput(ns(stringName))
)
Now you should see your plot appear with no problems.

how to delete warnings in reactive inputs in shiny

Could anyone can tell me why I get an error when I change a dataset in first selectInput widget? When I change a dataset from diamonds to mtcars I get an error Could not find 'carat' in input$bins and in the plot just for one second and after that everything works fine. Why it happened?
library(shiny)
library(ggplot2)
data(diamonds)
data(mtcars)
ui <- fluidPage(
column(3,
selectInput("data", "", choices = c('mtcars', 'diamonds')),
uiOutput('server_cols'),
uiOutput('server_bins')
),
column(9,
plotOutput("plot")
)
)
server <- function(input, output) {
data <- reactive({
switch(input$data,
diamonds = diamonds,
mtcars = mtcars)
})
output$server_cols <- renderUI({
data <- data()
nam <- colnames(data)
selectInput('cols', "Choose numeric columns:", choices = nam[sapply(data, function(x) is.numeric(x))])
})
output$server_bins <- renderUI({
if (!is.null(input$cols)) {
df <- data()
x <- eval(input$cols)
max_value <- max(df[,x])
sliderInput('bins','Choose number of bins:', min = 0.1,
max = max_value,
value = max_value/2)
}
})
output$plot <- renderPlot({
if (!is.null(input$cols) & !is.null(input$bins)) {
basicData <- data()
var <- eval(input$cols)
ggplot(basicData, aes_string(var)) +
geom_histogram(binwidth = input$bins, color = 'white', fill = 'red')
}
})
}
shinyApp(ui, server)
Your respective output objects respond to any changes of your input variables. Thus, when you change your dataset via input$data, the plot rebuilds itself, although input$cols did not yet adjust. Actually, try inserting some print("a") inside the output$plot to see that it is called up to three times if you change input$data.
The fix is to rethink your reaction logic and let your elements respond only to specific changes, to get some kind of response "thread".
For example, input$data should only trigger output$server_cols. And output$server_bins should only be triggered by input$cols (because this already implies that input$data changed earlier). Ultimately, output$plot just has to listen to changes of input$bins (because changes in input$cols and input$data always result in changes of input$bins since it is at the end of the thread).
Here is my suggestion using isolate.
library(shiny)
library(ggplot2)
data(diamonds)
data(mtcars)
ui <- fluidPage(
column(3,
selectInput("data", "", choices = c('mtcars', 'diamonds')),
uiOutput('server_cols'),
uiOutput('server_bins')
),
column(9,
plotOutput("plot")
)
)
server <- function(input, output) {
data <- reactive({
switch(input$data, diamonds = diamonds, mtcars = mtcars)
})
output$server_cols <- renderUI({
data <- data()
nam <- colnames(data)
selectInput('cols', "Choose numeric columns:", choices = nam[sapply(data, function(x) is.numeric(x))])
})
output$server_bins <- renderUI({
if (!is.null(input$cols)) {
df <- isolate(data())
x <- eval(input$cols)
max_value <- max(df[,x])
sliderInput('bins','Choose number of bins:', min = 0.1, max = max_value, value = max_value/2)
}
})
output$plot <- renderPlot({
if (!is.null(isolate(input$cols)) & !is.null(input$bins)) {
basicData <- isolate(data())
var <- eval(isolate(input$cols))
ggplot(basicData, aes_string(var)) +
geom_histogram(binwidth = input$bins, color = 'white', fill = 'red')
}
})
}
shinyApp(ui, server)
You might also want to look into updateSelectInput and updateSliderInput if you want to alter Input Elements depending on other input.

How to access a column of a DataFrame from a passed variable in Shiny?

I'm trying to create a simple shiny app where the user can select a variable from a drop down menu and then a plot is generated. The selected variable is seen as input$Feature w/in the server function but I am getting errors when trying to access the column of my data frame as df$input$Feature. I'm not sure how to do this.
bw <- read.xls('filename')
ui <- fluidPage(
selectInput(inputId = 'Feature',
label = 'Select a feature to plot:',
c(colnames(bw))),
plotOutput('graph')
)
server <- function(input, output){
output$graph <- renderPlot({
p <- ggplot(bw, aes(bw$Date))
p <- p + geom_line(aes(y=bw$input$Feature, colour='red', group=1))
p <- p + labs(x = 'Date', y = 'Feature Name')
print(p)
})
}
shinyApp(ui=ui, server=server)
Try using this in the geom_line instead:
bw[,input$Feature]
Can't be of much more help without having a reproducible example to work with.
EDIT:
This worked for me:
bw <- mtcars
library(shiny)
ui <- fluidPage(
selectInput(inputId = 'Feature',
label = 'Select a feature to plot:',
c(colnames(bw)),
selected=colnames(bw)[1]),
verbatimTextOutput('value'),
plotOutput('graph')
)
server <- function(input, output){
output$value <- renderPrint(columname())
columname <- reactive({input$Feature})
output$graph <- renderPlot({
p <- ggplot(bw, aes(bw$qsec))+ geom_line(aes_string(y=bw[, input$Feature]))
p <- p + labs(x = 'Date', y = 'Feature Name')
p
})
}
shinyApp(ui=ui, server=server)

Resources