I built the shiny app below that updates the line graph based on the user's input. It works fine until I try to generate a 2nd output. How can I display the value total.weight calculated in the renderPlot() function? It seems to me my data set df and the variable total.weight should be created "outside" of the renderPlot() function but I have not figured out how.
ui.r
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Reproducible Example"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
sidebarPanel(
selectInput("ID", "group", c("A", "B"))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("plot1"),
verbatimTextOutput("text1")
)
)
))
server.r
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
df <- subset(df, group == input$ID)
total.weight <- sum(df$weight)
#Plot
ggplot(data=df, aes(x=df$years, y=df$weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({total.weight})
})
Output snapshot:
You can also create reactives:
server.R
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
df <- reactive({
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
df <- subset(df, group == input$ID)
})
total.weight <- reactive({
sum(df()$weight)
})
output$plot1 <- renderPlot({
#Plot
ggplot(data=df(), aes(x=years, y=weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({total.weight()})
})
The quick workaround is to put the total weight in a global varaiable:
total.weight <<- sum(df$weight)
The nice way to do it is to subset your data.frame within a reactive function:
shinyServer(function(input, output) {
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
reactive_df <- reactive(subset(df, group == input$ID))
output$plot1 <- renderPlot({
ggplot(data=reactive_df(), aes(x=years, y=weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({sum(reactive_df()$weight)})
})
Related
In Shiny, I want to create a reactive object, a dataframe, that updates a plot automatically when values in that object change. I am aware that one needs to use parentheses for that object in subsequent usage. For some reason, I am still getting the error "object of type 'closure' is not subsettable".
I have tried to reactive(), reactiveValues() and reactiveVal(), but none produce the desired result. Any ideas?
require(ggplot2)
library(shiny)
# data pre-processing
# loading data from local machine
data(mtcars)
df <- mtcars
# processe
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y-1, mean.y+1),
step = 0.5)
),
mainPanel(
plotOutput("plot")
))))
server <- function(input, output) {
df <- reactive({
relevant.values <- input$y.value
df <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
df
})
output$plot <- renderPlot({
mydata <- df()
# relevant.values <- input$y.value
# data <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
ggplot(mydata, aes(x = hp , y = mpg )) + geom_line()
})
}
shinyApp(ui, server)
I think that there are two problems with your code:
You can't create a reactive expression called df which modifies an object called df, i.e. the same as the expression;
The code which(df$mpg %in% relevant.values[1]:relevant.values[2]) does not filter the values of mpg between relevant.values[1] and relevant.values[2] but it selects the values of mpg which are exactly equal to relevant.values[1]:relevant.values[2].
I modified your script as follows:
library(ggplot2)
library(shiny)
# data pre-processing
# loading data from local machine
data(mtcars)
df <- mtcars
# processe
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(
inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y - 1, mean.y + 1),
step = 0.5
)
),
mainPanel(
plotOutput("plot")
)
)
))
server <- function(input, output) {
filtered_df <- reactive({
df[which(df$mpg >= input$y.value[1] & df$mpg <= input$y.value[2]), ]
})
output$plot <- renderPlot({
ggplot(filtered_df(), aes(x = hp, y = mpg)) + geom_line()
})
}
shinyApp(ui, server)
The error is primarily because you have an object called df which is a copy of mtcars as well as a reactive object called df.
Renaming your reactive is the easier fix:
require(ggplot2)
library(shiny)
# data pre-processing
# loading data from local machine
data(mtcars)
df <- mtcars
# processe
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y-1, mean.y+1),
step = 0.5)
),
mainPanel(
plotOutput("plot")
))))
server <- function(input, output) {
dfr <- reactive({
relevant.values <- input$y.value
df <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
df
})
output$plot <- renderPlot({
mydata <- dfr()
# relevant.values <- input$y.value
# data <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
ggplot(mydata, aes(x = hp , y = mpg )) + geom_line()
})
}
shinyApp(ui, server)
I did it like this, please try it and tell me if is ok.
require(ggplot2)
library(shiny)
data(mtcars)
df <- mtcars
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y-1, mean.y+1),
step = 0.5)
),
mainPanel(
plotOutput("plot")
))))
server <- function(input, output) {
output$plot<- renderPlot({
output$plot <- renderPlot({
a=input$y.value[1] ; b=input$y.value[2]
hp_reac <- df$hp[a:b]
mpg_reac <- df$mpg[a:b]
ggplot(df[a:b,], aes(x = hp_reac , y = mpg_reac )) + geom_line()
})
})
}
shinyApp(ui, server)
I'm having trouble with the server.R getting shiny to plot the data based on drop down selections from the ui.R. I would like to select a 'Site' and a 'Parameter' and plot the 'Obs' that reflects that 'Site' and 'Parameter'. Obs as the Y and Date on the X. Here is some sample code.
Site_Names=data.frame(c(A=rep("A",10),B=rep("B",10),C=rep("C",10)))
Site_Names=Site_Names[,1]
Parameters=data.frame(c(pH=rep("pH",10),DO=rep("DO",10),Temp=rep("Temp",10)))
Parameters=Parameters[,1]
Obs=rnorm(30)
Dates=c(seq(as.Date("2000/1/1"), by = "year", length.out =10 ),
seq(as.Date("2005/1/1"), by = "year", length.out =10 ),
seq(as.Date("1990/1/1"), by = "year", length.out =10 ))
data=data.frame(Site_Names,Parameters,Obs,Dates)
#ui.R
Sites=levels(data$Site_Name)
setNames(as.list(Sites), Sites)
params=levels(data$Parameters)
setNames(as.list(params), params)
library(shiny)
library(ggplot2)
shinyUI(fluidPage(
# Application title
titlePanel("Data"),
sidebarLayout(
sidebarPanel(
selectInput("site", "Select Site:", Sites),
selectInput("parameters", "parameter", params)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("Plot")
)
)
))
#server.R
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
dataset <- reactive({
data[ , (input$Sites),]
})
output$distPlot <- renderPlot({
p <- ggplot(dataset(), aes(x=Dates, y=input$params and input$Sites))
+ geom_point(data$Obs)
print(p)
})
You can use subset within your reactive expression to get the plot data. Be careful though, as you can end up with null values if the parameter isn't included in the site data.
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
dataset <- reactive({
subset(data, Site_Names == input$Sites & Parameters == input$params)
})
output$distPlot <- renderPlot({
p <- ggplot(dataset(), aes(x = Dates, y = Obs)) +
geom_line()
print(p)
})
I would like to display the filtered column criterium from datatable DT in Shiny R in a form of text or table (so that the user knows what he/she filtered while browsing through other tabs in ShinyApp).
Here is very simple example (no tabs) just to display:
library(shiny)
library(DT)
library(ggplot2)
x <- as.numeric(1:1000000)
y <- as.numeric(1:1000000)
data <- data.frame(x,y)
shinyApp(
ui = fluidPage(dataTableOutput('tableId'),
plotOutput('plot1')),
server = function(input, output) {
output$tableId = renderDataTable({
datatable(data, options = list(pageLength = 100, lengthMenu=c(100,200,300,400,500,600)))
})
output$plot1 = renderPlot({
filtered_data <- data[input$tableId_rows_all, ]
ggplot(data=filtered_data, aes(x=x,y=y)) + geom_line()
})
}
)
So for example if we filter x column from 10-100, is it possible to display it as a text under the plot (and in my original ShinyApp in the other tab in tabsetPanel): X column has been filtered 10-100 or anything like that.
Thanks for any tips!
Cheers
You can get such info from tableId_search_columns
for example
library(shiny)
library(DT)
library(ggplot2)
x <- as.numeric(1:10000)
y <- as.numeric(1:10000)
data <- data.frame(x,y)
shinyApp(
ui = fluidPage(dataTableOutput('tableId'),
plotOutput('plot1'),
verbatimTextOutput("txt")),
server = function(input, output) {
output$tableId = renderDataTable({
datatable(data,filter="top", options = list(pageLength = 100, lengthMenu=c(100,200,300,400,500,600)))
})
output$plot1 = renderPlot({
filtered_data <- data[input$tableId_rows_all, ]
ggplot(data=filtered_data, aes(x=x,y=y)) + geom_line()
})
output$txt=renderText({
aa=""
for ( i in 1:length(input$tableId_search_columns)){
if(input$tableId_search_columns[[i]]!=""){
aa=paste0(aa,"\n","column ",i, "filter ",input$tableId_search_columns[[i]])}
}
aa
})
}
)
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)
I am having issues displaying ggplot (or any form of charts like hist()). I have tried looking through Stack Overflow but the solutions provided were not useful for this instance. I have not been able to display any of the graphs successfully.
I am using R studio with 3.2.0 build, deploying on Shinyapps.io and viewing via Chrome. I am able to display the graph within R but unable to display it when running with shiny.
Is this a code issue or something I had missed out from my packages? (Note: I have reduced my code trying to troubleshoot, so the variables from ui.R are not used in server.R.)
ui.R
library(shiny)
library(ggplot2)
dataset <- diamonds
diamondcolours <- unique( dataset["color"], incomparables = FALSE)
diamondcolours <- lapply(diamondcolours, as.character)
diamondcuts <- unique( dataset["cut"], incomparables = FALSE)
diamondcuts <- lapply(diamondcuts, as.character)
diamondclarity <- unique( dataset["clarity"], incomparables = FALSE)
diamondclarity <- lapply(diamondclarity, as.character)
carat <- dataset["carat"]
mincarat <- min(carat[ carat != min(carat) ])
# mincarat
maxcarat <- max(carat[ carat != max(carat) ])
# maxcarat
fluidPage(
titlePanel("Diamonds"),
sidebarPanel(
sliderInput('carat', 'Carat', min=mincarat, max=maxcarat,
value=mincarat, step=0.01, round=0),
selectInput('cut', 'Cut', diamondcuts$cut),
selectInput('color', 'Color', diamondcolours$color),
selectInput('clarity', 'Clarity', diamondclarity$clarity)
),
mainPanel(
plotOutput(outputId = 'mainplot')
)
)
server.R
library(shiny)
library(ggplot2)
dataset <- diamonds()
shinyServer(function(input, output, session) {
values <- reactiveValues()
testset <- dataset[ which(dataset$color == values$dcolor & dataset$carat > values$dcarat & dataset$clarity == values$dclarity & dataset$cut== values$dcut ), ]
output$mainplot <- renderPlot({
p <- ggplot(dataset[dataset$price <= 326,], aes(x = carat, y = color))
p <- p + geom_point()
print(p)
} )
Some of the more important problems: (1) data should be reactive to user input, (2) the variable names referring to input are incorrect, (3) all of the code in UI should be in server or, if it's not meant to be reactive, in the global environment. Here is a simplified version that runs,
library(shiny)
library(ggplot2)
dataset(diamonds)
## ** From UI: variables defined here can be seen in the whole app
mincarat <- min(diamonds$carat)
maxcarat <- max(diamonds$carat)
shinyApp(
shinyUI(
fluidPage(
titlePanel("Diamonds"),
sidebarPanel(
sliderInput('dcarat', 'Carat', min=mincarat, max=maxcarat,
value=mincarat, step=0.01, round=0),
selectInput('dcut', 'Cut', levels(diamonds$cut)),
selectInput('dcolor', 'Color', levels(diamonds$color)),
selectInput('dclarity', 'Clarity', levels(diamonds$clarity))
),
mainPanel(
plotOutput('mainplot')
)
)
),
shinyServer(function(input, output) {
## values <- reactiveValues() # unused
## Your data should be reactive - and reference `input`
## to get user-entered values
rxData <- reactive({
dat <- with(diamonds,
diamonds[color == input$dcolor &
carat > input$dcarat &
clarity == input$dclarity &
cut == input$dcut, ])
dat
})
output$mainplot <- renderPlot({
dataset <- rxData() # this is the subsetted data
p <- ggplot(dataset, aes(x = carat, y = price))
p <- p + geom_point()
print(p)
})
})
)
There are number of errors in that code:
You are missing to brackets at the end of the server.R
You are not reading your data correctly
Amended file:
library(shiny)
library(ggplot2)
shinyServer(function(input, output, session) {
data("diamonds")
dataset <- diamonds
rm(diamonds)
values <- reactiveValues()
testset <- dataset[ which(dataset$color == values$dcolor & dataset$carat > values$dcarat & dataset$clarity == values$dclarity & dataset$cut== values$dcut ), ]
output$mainplot <- renderPlot({
p <- ggplot(dataset[dataset$price <= 326,], aes(x = carat, y = color))
p <- p + geom_point()
print(p)
})
})
The ui.R is also wrong. You should put that stuff at the beginning in global.R as per guidelines on scoping rules in Shiny.