I want to adapt this code to be able to choose which plot I want to download in pdf format. I have tried to assign the plot to an object called "p1" for plot1 and "p2" for plot2 and then call the objects in each condition but it doesn't work.
The only way it works is as it is now that I put the complete function of the plot, but I can't choose which of the two.
I also want to put the download button inside the sidebarPanel but then it stops working. How can I make it to be in the sidebar?
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
titlePanel("Download base plot in Shiny - an example"),
sidebarLayout(
sidebarPanel(
selectInput(inputId = "var1", label = "Select the X variable", choices = c("Sepal.Length" = 1, "Sepal.Width" = 2, "Petal.Length" = 3, "Petal.Width" = 4)),
selectInput(inputId = "var2", label = "Select the Y variable", choices = c("Sepal.Length" = 1, "Sepal.Width" = 2, "Petal.Length" = 3, "Petal.Width" = 4), selected = 2),
radioButtons(inputId = "var3", label = "Select the plot", choices = list("plot1", "plot2"))
),
mainPanel(
plotOutput("plot"),
plotOutput("plot2"),
downloadButton(outputId = "down", label = "Download the plot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# x contains all the observations of the x variable selected by the user. X is a reactive function
x <- reactive({
iris[,as.numeric(input$var1)]
})
# x contains all the observations of the y variable selected by the user. Y is a reactive function
y <- reactive({
iris[,as.numeric(input$var2)]
})
# xl contains the x variable or column name of the iris dataset selected by the user
xl <- reactive({
names(iris[as.numeric(input$var1)])
})
# yl contains the y variable or column name of the iris dataset selected by the user
yl <- reactive({
names(iris[as.numeric(input$var2)])
})
# render the plot so could be used to display the plot in the mainPanel
output$plot <- renderPlot({
plot(x=x(), y=y(), main = "iris dataset plot", xlab = xl(), ylab = yl())
})
# render the plot so could be used to display the plot in the mainPanel
output$plot2 <- renderPlot({
plot(x=x(), y=y(), main = "iris plot 2", xlab = xl(), ylab = yl(), col = "blue")
})
# downloadHandler contains 2 arguments as functions, namely filename, content
output$down <- downloadHandler(
filename = function() {
paste("iris", input$var3, sep=".")
},
# content is a function with argument file. content writes the plot to the device
content = function(file) {
if(input$var3 == "plot1")
pdf(file) # open the png device
# if(input$var3 == "png2")
# pdf(file)
else
pdf(file) # open the pdf device
plot(x=x(), y=y(), main = "iris dataset plot", xlab = xl(), ylab = yl())
dev.off() # turn the device off
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
You can use recordPlot() to put the plot in an object and replayPlot() in an opened device:
library(shiny)
# Define UI
ui <- fluidPage(
titlePanel("Download base plot in Shiny - an example"),
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "var1", label = "Select the X variable",
choices = c(
"Sepal.Length" = 1,
"Sepal.Width" = 2,
"Petal.Length" = 3,
"Petal.Width" = 4
)
),
selectInput(
inputId = "var2", label = "Select the Y variable",
choices = c(
"Sepal.Length" = 1,
"Sepal.Width" = 2,
"Petal.Length" = 3,
"Petal.Width" = 4
),
selected = 2
),
radioButtons(
inputId = "var3", label = "Select the plot",
choices = list("plot1", "plot2")
)
),
mainPanel(
plotOutput("plot"),
plotOutput("plot2"),
downloadButton(outputId = "down", label = "Download the plot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# x contains all the observations of the x variable selected by the user. X is a reactive function
x <- reactive({
iris[, as.numeric(input$var1)]
})
# x contains all the observations of the y variable selected by the user. Y is a reactive function
y <- reactive({
iris[, as.numeric(input$var2)]
})
# xl contains the x variable or column name of the iris dataset selected by the user
xl <- reactive({
names(iris[as.numeric(input$var1)])
})
# yl contains the y variable or column name of the iris dataset selected by the user
yl <- reactive({
names(iris[as.numeric(input$var2)])
})
Plot1 <- reactive({
plot(
x=x(), y=y(), main = "iris dataset plot", xlab = xl(), ylab = yl()
)
recordPlot()
})
Plot2 <- reactive({
plot(
x=x(), y=y(), main = "iris plot 2", xlab = xl(), ylab = yl(), col = "blue"
)
recordPlot()
})
# render the plot so could be used to display the plot in the mainPanel
output$plot <- renderPlot({
Plot1()
})
# render the plot so could be used to display the plot in the mainPanel
output$plot2 <- renderPlot({
Plot2()
})
# downloadHandler contains 2 arguments as functions, namely filename, content
output$down <- downloadHandler(
filename = function() {
paste("iris", input$var3, "pdf", sep=".")
},
# content is a function with argument file. content writes the plot to the device
content = function(file) {
if(input$var3 == "plot1"){
pdf(file)
replayPlot(Plot1())
dev.off()
}else{
pdf(file)
replayPlot(Plot2())
dev.off()
}
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
Related
I am struggling with getting the code to work for this log widget I want to add to my interactive plot in shiny. I am able to modify the graphs x and y axis to a log scale by adding log(dat()[[input$yvrbl]]) to the server coder
server <- function(input, output) {
x <- reactive({
log(dat()[[input$yvrbl]])
})
y <- reactive({
log(dat()[[input$yvrbl]])
})
I was able to create the widgets on the ui code as well. I am still unable to transform the data to the log version based on whether or not the widget is checked. I tried making a separate reactive expression to host the changed log version of the x and y axis depending on an if statement. Please let me know what else I can do.
library(shiny)
library(plotly)
library(tibble)
library(tidyverse)
library(tidyr)
library(readr)
library(dplyr)
library(ggplot2)
# set working directory
setwd("~/BDSWD")
#read data
gm <- read_csv("gapminder_clean.csv")
# Define UI ----
ui <- fluidPage(
column(3,offset = 4, titlePanel("Explore Gapminder Data with Shiny")),
headerPanel('Graphs'),
mainPanel(
plotlyOutput('plot')
),
sidebarPanel(
#variable selection for x-axis
selectInput(inputId ='xvrbl', #The input slot that will be used to access the value.
label = 'X-Axis Variable', #Display label for the control, or NULL for no label.
choices = colnames(gm), #List of values to select from
selected = 'CO2 emissions (metric tons per capita)'
),
checkboxInput(inputId = "LogX",
label = "Log Transform",
value = FALSE),
#variable selection for y-axis
selectInput(inputId ='yvrbl', #The input slot that will be used to access the value.
label = 'Y-Axis Variable', #Display label for the control, or NULL for no label.
choices = colnames(gm), #List of values to select from
selected = 'gdpPercap'
),
checkboxInput(inputId = "LogY",
label = "Log Transform",
value = FALSE),
#date range - slider
sliderInput(inputId = "time",
label = "Years",
min = min(gm$Year),
max = max(gm$Year),
step = 5,
value = c(min(gm$Year),max(gm$Year)))
)
)
server <- function(input, output) {
x <- reactive({
dat()[[input$xvrbl]]
})
y <- reactive({
dat()[[input$yvrbl]]
})
dat <- reactive({
subset(gm, Year %in% input$time)
})
lgrthmc <- reactive({
if(isTRUE(input$LogY)) {
y <- reactive({
log(dat()[[input$yvrbl]])
})
} else {}
if(isTRUE(input$LogX)) {
x <- reactive({
log(dat()[[input$xvrbl]])
})
} else {}
})
output$plot <- renderPlotly({
plot_ly(
x = x(),
y = y(),
type = "scatter",
mode = "markers",
color = dat()$continent
) %>%
layout(
title = 'Gapminder Dataset',
plot_bgcolor = "#e5ecf6",
xaxis = list(title = input$xvrbl),
yaxis = list(title = input$yvrbl),
legend = list(title=list(text='<b> Continent </b>'))
)
})
}
# Run the app
shinyApp(ui = ui, server = server)
Instead of wrapping reactives inside a reactive you could achieve your desired result by adding an if inside your reactives, e.g.
Note: I slightly adjusted the subsetting of your data to take the sliderInput into account.
x <- reactive({
x <- dat()[[input$xvrbl]]
if (input$LogX) x <- log(x)
return(x)
})
library(gapminder)
library(shiny)
library(plotly)
library(tidyverse)
gm <- gapminder |> rename(Year = year)
# Define UI ----
ui <- fluidPage(
column(3, offset = 4, titlePanel("Explore Gapminder Data with Shiny")),
headerPanel("Graphs"),
mainPanel(
plotlyOutput("plot")
),
sidebarPanel(
# variable selection for x-axis
selectInput(
inputId = "xvrbl", # The input slot that will be used to access the value.
label = "X-Axis Variable", # Display label for the control, or NULL for no label.
choices = colnames(gm), # List of values to select from
selected = "lifeExp"
),
checkboxInput(inputId = "LogX",
label = "Log Transform",
value = FALSE),
# variable selection for y-axis
selectInput(
inputId = "yvrbl", # The input slot that will be used to access the value.
label = "Y-Axis Variable", # Display label for the control, or NULL for no label.
choices = colnames(gm), # List of values to select from
selected = "gdpPercap"
),
checkboxInput(
inputId = "LogY",
label = "Log Transform",
value = FALSE
),
# date range - slider
sliderInput(
inputId = "time",
label = "Years",
min = min(gm$Year),
max = max(gm$Year),
step = 5,
value = range(gm$Year)
)
)
)
server <- function(input, output) {
x <- reactive({
x <- dat()[[input$xvrbl]]
if (input$LogX) x <- log(x)
return(x)
})
y <- reactive({
y <- dat()[[input$yvrbl]]
if (input$LogY) y <- log(y)
return(y)
})
dat <- reactive({
subset(gm, Year >= input$time[[1]], Year <= input$time[[2]])
})
output$plot <- renderPlotly({
plot_ly(
x = x(),
y = y(),
type = "scatter",
mode = "markers",
color = dat()$continent
)
})
}
# Run the app
shinyApp(ui = ui, server = server)
#>
#> Listening on http://127.0.0.1:6593
I am trying to create a basic shiny app from the iris dataset, code below. However, when I try to look at the resulting graph all of my points are collapsed, as if neither axis has a scale.
# Load libraries
library(ggplot2)
library(shiny)
library(dplyr)
# Load dataset locally
df <- iris
# Define UI for application
ui <- fluidPage(# Application title
titlePanel("Shiny Attempt"),
sidebarLayout(
# sidebar
sidebarPanel(
# Graph 1 input
checkboxGroupInput(
inputId = "x",
label = "X axis",
choices = c("Sepal Length" = "Sepal.Length",
"Sepal Width" = "Sepal.Width"),
selected = "Sepal.Width"
),
checkboxGroupInput(
inputId = "y",
label = "Y axis",
choices = c("Petal Length" = "Petal.Length",
"Petal Width" = "Petal.Width"),
selected = "Petal.Width"
)
),
# main panel
mainPanel(
# Graph 1 output
plotOutput(outputId = "graph_1"))
))
# Define server logic required to draw plot
server <- function(input, output) {
output$graph_1 <- renderPlot({
# plot inputs
# draw the visualization
ggplot(df, aes(
x = input$x,
y = input$y,
color = Species
)) +
geom_point()
})
}
# Run the application
shinyApp(ui = ui, server = server)
If I run the ggplot portion separate from the shiny app, the graph displays properly.
ggplot(iris, aes(
x = Sepal.Width,
y = Petal.Width,
color = Species
)) +
geom_point()
I guess I could add a scale to both axes, but when I look at other shiny app examples, it doesn't appear to be needed to display correctly. What step am I missing with the shiny app?
Try this, you have to use aes_string() because your values are strings:
# Load libraries
library(ggplot2)
library(shiny)
library(dplyr)
# Load dataset locally
df <- iris
# Define UI for application
ui <- fluidPage(# Application title
titlePanel("Shiny Attempt"),
sidebarLayout(
# sidebar
sidebarPanel(
# Graph 1 input
checkboxGroupInput(
inputId = "x",
label = "X axis",
choices = c("Sepal Length" = "Sepal.Length",
"Sepal Width" = "Sepal.Width"),
selected = "Sepal.Width"
),
checkboxGroupInput(
inputId = "y",
label = "Y axis",
choices = c("Petal Length" = "Petal.Length",
"Petal Width" = "Petal.Width"),
selected = "Petal.Width"
)
),
# main panel
mainPanel(
# Graph 1 output
plotOutput(outputId = "graph_1"))
))
# Define server logic required to draw plot
server <- function(input, output) {
output$graph_1 <- renderPlot({
# plot inputs
# draw the visualization
ggplot(df, aes_string(
x = input$x,
y = input$y,
color = 'Species'
)) +
geom_point()
})
}
# Run the application
shinyApp(ui = ui, server = server)
I have a shiny app which generates 2 plots and one table. As you will see I want to select which one of them will be displayed every time based on the radiobuttons() input. Until now I get an error object of type 'closure' is not subsettable Which object exactly is of type closure? Note that the first is a ggplot object the second is a plotly object and the third a datatable.
# ui.R
library(shiny)
library(plotly)
pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
uiOutput("filter_degree")
),
mainPanel(
uiOutput('plot')
)
)
#server.r
function(input, output, session) {
output$filter_degree<-renderUI({
radioButtons("rd","Select Option",choices = c("Mileage","Regression",'Table'),
selected = "Mileage")
})
output$plot <- renderUI({
if(input$rd=="Mileage"){
output$plot1<-renderUI({
# Boxplots of mpg by number of gears
# observations (points) are overlayed and jittered
qplot(gear, mpg, data=mtcars, geom=c("boxplot", "jitter"),
fill=gear, main="Mileage by Gear Number",
xlab="", ylab="Miles per Gallon")
})
}
else if(input$rd=="Regression"){
output$plot2<-renderUI({
x <- c(1:100)
random_y <- rnorm(100, mean = 0)
data <- data.frame(x, random_y)
p <- plot_ly(data, x = ~x, y = ~random_y, type = 'scatter', mode = 'lines')
})
}
else if(input$rd=="Table"){
output$tbl = DT::renderDataTable(datatable(
iris, options = list(lengthChange = FALSE,scrollY = T, scroller = TRUE, scrollX = T),selection = list(target="cell",mode="single"),rownames = F)
)
}
})
}
You need to provide the plot/table output as part of the if/then sequence (plotOutput("plot1"), etc.). Otherwise, it has nothing to render. Also, there appears to be an error in the ploty call, but I haven't fixed it for you.
library(shiny)
library(DT)
library(plotly)
ui <- pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
uiOutput("filter_degree")
),
mainPanel(
uiOutput('plot')
)
)
#server.r
server <- function(input, output, session) {
output$filter_degree<-renderUI({
radioButtons("rd","Select Option",choices = c("Mileage","Regression",'Table'),
selected = "Mileage")
})
output$plot <- renderUI({
if(input$rd=="Mileage"){
output$plot1<-renderPlot({
# Boxplots of mpg by number of gears
# observations (points) are overlayed and jittered
qplot(gear, mpg, data=mtcars, geom=c("boxplot", "jitter"),
fill=gear, main="Mileage by Gear Number",
xlab="", ylab="Miles per Gallon")
})
plotOutput("plot1")
}
else if(input$rd=="Regression"){
output$plot2<-renderUI({
x <- c(1:100)
random_y <- rnorm(100, mean = 0)
data <- data.frame(x, random_y)
p <- plot_ly(data, x = ~x, y = ~random_y, type = 'scatter', mode = 'lines')
})
plotlyOutput("plot2")
}
else if(input$rd=="Table"){
output$tbl = DT::renderDataTable(datatable(
iris, options = list(lengthChange = FALSE,scrollY = T, scroller = TRUE, scrollX = T),selection = list(target="cell",mode="single"),rownames = F)
)
dataTableOutput("tbl")
}
})
}
shinyApp(ui = ui, server = server)
I am trying to save a ggplot2 object made in a shiny app. Basically this code allows .xlsx files to be uploaded and plots created after selecting from some options. I have then included a download button so that the user may download the plot they have created. I am using downloadHandler() and grDevices::png(). Pressing the button does cause a .png file to be downloaded, but when I open it, it is just a blank, white square. I am so close! Any help would be much appreciated. Thank you.
#initialize
library(shiny)
library(ggplot2)
library(purrr)
library(dplyr)
library(plotly)
#example data
data(iris)
#make some factors
#easier to let ggplot2 control plotting (color, fill) based on type
data(mtcars)
uvals<-sapply(mtcars,function(x){length(unique(x))})
mtcars<-map_if(mtcars,uvals<4,as.factor) %>%
as.data.frame()
#plotting theme for ggplot2
.theme<- theme(
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()
)
# UI for app
ui<-(pageWithSidebar(
# title
headerPanel("Select Options"),
#input
sidebarPanel
(
# Input: Select a file ----
fileInput("file1", "Choose xlsx File",
multiple = TRUE,
accept = c(".xlsx")),
# Horizontal line ----
tags$hr(),
#download button
fluidPage(downloadButton('down')),
# Input: Select what to display
selectInput("dataset","Data:",
choices =list(iris = "iris", mtcars = "mtcars",
uploaded_file = "inFile"), selected=NULL),
selectInput("xaxis","X axis:", choices = NULL),
selectInput("yaxis","Y axis:", choices = NULL),
selectInput("fill","Fill:", choices = NULL),
selectInput("group","Group:", choices = NULL),
selectInput("plot.type","Plot Type:",
list(boxplot = "boxplot", histogram = "histogram", density = "density", bar = "bar")
),
checkboxInput("show.points", "show points", TRUE)
),
# output
mainPanel(
h3(textOutput("caption")),
#h3(htmlOutput("caption")),
uiOutput("plot") # depends on input
)
))
# shiny server side code for each call
server<-function(input, output, session){
#update group and
#variables based on the data
observe({
#browser()
if(!exists(input$dataset)) return() #make sure upload exists
var.opts<-colnames(get(input$dataset))
updateSelectInput(session, "xaxis", choices = var.opts)
updateSelectInput(session, "yaxis", choices = var.opts)
updateSelectInput(session, "fill", choices = var.opts)
updateSelectInput(session, "group", choices = var.opts)
})
output$caption<-renderText({
switch(input$plot.type,
"boxplot" = "Boxplot",
"histogram" = "Histogram",
"density" = "Density plot",
"bar" = "Bar graph")
})
output$plot <- renderUI({
plotOutput("p")
})
#get data object
get_data<-reactive({
if(!exists(input$dataset)) return() # if no upload
check<-function(x){is.null(x) || x==""}
if(check(input$dataset)) return()
obj<-list(data=get(input$dataset),
yaxis=input$yaxis,
xaxis=input$xaxis,
fill=input$fill,
group=input$group
)
#require all to be set to proceed
if(any(sapply(obj,check))) return()
#make sure choices had a chance to update
check<-function(obj){
!all(c(obj$yaxis,obj$xaxis, obj$fill,obj$group) %in% colnames(obj$data))
}
if(check(obj)) return()
obj
})
#plotting function using ggplot2
output$p <- renderPlot({
plot.obj<-get_data()
#conditions for plotting
if(is.null(plot.obj)) return()
#make sure variable and group have loaded
if(plot.obj$yaxis == "" | plot.obj$xaxis =="" | plot.obj$fill ==""| plot.obj$group =="") return()
#plot types
plot.type<-switch(input$plot.type,
"boxplot" = geom_boxplot(),
"histogram" = geom_histogram(alpha=0.5,position="identity"),
"density" = geom_density(alpha=.75),
"bar" = geom_bar(position="dodge")
)
if(input$plot.type=="boxplot") { #control for 1D or 2D graphs
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
y = plot.obj$yaxis,
fill = plot.obj$fill,# let type determine plotting
group = plot.obj$group
)
) + plot.type
if(input$show.points==TRUE)
{
p<-p+ geom_point(color='black',alpha=0.5, position = 'jitter')
}
} else {
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
fill = plot.obj$fill,
group = plot.obj$group
#color = as.factor(plot.obj$group)
)
) + plot.type
}
p<-p+labs(
fill = input$fill,
x = "",
y = input$yaxis
) +
.theme
print(p)
})
# set uploaded file
upload_data<-reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
#could also store in a reactiveValues
read_excel(inFile$datapath)
})
observeEvent(input$file1,{
inFile<<-upload_data()
})
# downloadHandler contains 2 arguments as functions, namely filename, content
output$down <- downloadHandler(
filename = function() {
paste(input$dataset,"png" , sep=".")
},
# content is a function with argument file. content writes the plot to the device
content = function(file) {
png(file) # open the png device
p # for GGPLOT
dev.off() # turn the device off
}
)
}
# Create Shiny app ----
shinyApp(ui, server)
I responded as a comment, but I recognize it's a little hard to follow, so I'll post the full revised code to make it clearer.
I generally recommend to not do too much within render*() calls. Rather, set up the object you're looking to create in a separate reactive() object, and just refer to that in renderPlot(). In the code below, I moved all your code that creates the plot into a reactive object named p, and then I can refer to it in ggsave() for the downloading.
#initialize
library(shiny)
library(ggplot2)
library(purrr)
library(dplyr)
library(plotly)
#example data
data(iris)
#make some factors
#easier to let ggplot2 control plotting (color, fill) based on type
data(mtcars)
uvals<-sapply(mtcars,function(x){length(unique(x))})
mtcars<-map_if(mtcars,uvals<4,as.factor) %>%
as.data.frame()
#plotting theme for ggplot2
.theme<- theme(
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()
)
# UI for app
ui<-(pageWithSidebar(
# title
headerPanel("Select Options"),
#input
sidebarPanel
(
# Input: Select a file ----
fileInput("file1", "Choose xlsx File",
multiple = TRUE,
accept = c(".xlsx")),
# Horizontal line ----
tags$hr(),
#download button
fluidPage(downloadButton('down')),
# Input: Select what to display
selectInput("dataset","Data:",
choices =list(iris = "iris", mtcars = "mtcars",
uploaded_file = "inFile"), selected=NULL),
selectInput("xaxis","X axis:", choices = NULL),
selectInput("yaxis","Y axis:", choices = NULL),
selectInput("fill","Fill:", choices = NULL),
selectInput("group","Group:", choices = NULL),
selectInput("plot.type","Plot Type:",
list(boxplot = "boxplot", histogram = "histogram", density = "density", bar = "bar")
),
checkboxInput("show.points", "show points", TRUE)
),
# output
mainPanel(
h3(textOutput("caption")),
#h3(htmlOutput("caption")),
uiOutput("plot") # depends on input
)
))
# shiny server side code for each call
server<-function(input, output, session){
#update group and
#variables based on the data
observe({
#browser()
if(!exists(input$dataset)) return() #make sure upload exists
var.opts<-colnames(get(input$dataset))
updateSelectInput(session, "xaxis", choices = var.opts)
updateSelectInput(session, "yaxis", choices = var.opts)
updateSelectInput(session, "fill", choices = var.opts)
updateSelectInput(session, "group", choices = var.opts)
})
output$caption<-renderText({
switch(input$plot.type,
"boxplot" = "Boxplot",
"histogram" = "Histogram",
"density" = "Density plot",
"bar" = "Bar graph")
})
output$plot <- renderUI({
plotOutput("p")
})
#get data object
get_data<-reactive({
if(!exists(input$dataset)) return() # if no upload
check<-function(x){is.null(x) || x==""}
if(check(input$dataset)) return()
obj<-list(data=get(input$dataset),
yaxis=input$yaxis,
xaxis=input$xaxis,
fill=input$fill,
group=input$group
)
#require all to be set to proceed
if(any(sapply(obj,check))) return()
#make sure choices had a chance to update
check<-function(obj){
!all(c(obj$yaxis,obj$xaxis, obj$fill,obj$group) %in% colnames(obj$data))
}
if(check(obj)) return()
obj
})
p <- reactive({
plot.obj<-get_data()
#conditions for plotting
if(is.null(plot.obj)) return()
#make sure variable and group have loaded
if(plot.obj$yaxis == "" | plot.obj$xaxis =="" | plot.obj$fill ==""| plot.obj$group =="") return()
#plot types
plot.type<-switch(input$plot.type,
"boxplot" = geom_boxplot(),
"histogram" = geom_histogram(alpha=0.5,position="identity"),
"density" = geom_density(alpha=.75),
"bar" = geom_bar(position="dodge")
)
if(input$plot.type=="boxplot") { #control for 1D or 2D graphs
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
y = plot.obj$yaxis,
fill = plot.obj$fill,# let type determine plotting
group = plot.obj$group
)
) + plot.type
if(input$show.points==TRUE)
{
p<-p+ geom_point(color='black',alpha=0.5, position = 'jitter')
}
} else {
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
fill = plot.obj$fill,
group = plot.obj$group
#color = as.factor(plot.obj$group)
)
) + plot.type
}
p<-p+labs(
fill = input$fill,
x = "",
y = input$yaxis
) +
.theme
print(p)
})
#plotting function using ggplot2
output$p <- renderPlot({
p()
})
# set uploaded file
upload_data<-reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
#could also store in a reactiveValues
read_excel(inFile$datapath)
})
observeEvent(input$file1,{
inFile<<-upload_data()
})
# downloadHandler contains 2 arguments as functions, namely filename, content
output$down <- downloadHandler(
filename = function() {
paste(input$dataset,"png" , sep=".")
},
# content is a function with argument file. content writes the plot to the device
content = function(file) {
ggsave(file, p())
}
)
}
# Create Shiny app ----
shinyApp(ui, server)
I saw this app https://rich.shinyapps.io/regression/ and I wanted to do something similar displaying the regression output as html.
I divided my app in three parts as below.
server.R has no "engine" problems and the regression result is correct and pander is converting summary() to markdown correctly.
ui.R is also working ok but the markdown displayed after htmlOutput("model") is suppossed to be obtained from
output$model <- renderPrint({
pander(summary(model()))
})
in server.R, and the table is not well displayed even when its a valid markdown table.
How can I display my markdown summary as a common table like in R Markdown? my current output is:
Full MWE of the app
global.R
#library(shinyapps)
library(googleVis)
library(knitr)
library(pander)
library(shiny)
#library(shinysky)
ui.R
# Define UI for application
shinyUI(fluidPage(
# Application title
titlePanel("Bivariate Regression"),
# Sidebar
sidebarLayout(
sidebarPanel(
textInput("name", label = h5("Name"), value = "Name"),
HTML('</br>'),
#selectInput("dataset", h5("Choose a dataset:"), choices = c("cars", "longley", "MLB","rock", "pressure")),
selectInput("dataset", h5("Choose a dataset:"), choices = c("cars", "longley","rock", "pressure")),
HTML('</br>'),
uiOutput('dv'),
HTML('</br>'),
uiOutput('iv'),
HTML('</br>')),
#radioButtons('format', h5('Document format'), c('PDF', 'HTML', 'Word'), inline = TRUE),
#downloadButton('downloadReport')),
#includeHTML('help.html')),
# main panel
mainPanel(
tabsetPanel(type = "tabs",
tabPanel("Data",
HTML("</br>Select a data set from the 'Choose a dataset menu' or enter your own data below </br> </br>"),
numericInput("obs", label = h5("Number of observations to view"), 10),
tableOutput("view")),
tabPanel("Summary Statistics",
verbatimTextOutput("summary"),
textInput("text_summary", label = "Interpretation", value = "Enter text...")),
tabPanel("Model",
htmlOutput("model"),
textInput("text_model", label = "Interpretation", value = "Enter text..."))
)
))
))
server.R
shinyServer(function(input, output) {
# list of data sets
datasetInput <- reactive({
switch(input$dataset,
"cars" = mtcars,
"longley" = longley,
"MLB" = mlb11,
"rock" = rock,
"pressure" = pressure,
"Your Data" = df())
})
# dependent variable
output$dv = renderUI({
selectInput('dv', h5('Dependent Variable'), choices = names(datasetInput()))
})
# independent variable
output$iv = renderUI({
selectInput('iv', h5('Independent Variable'), choices = names(datasetInput()))
})
# regression formula
regFormula <- reactive({
as.formula(paste(input$dv, '~', input$iv))
})
# bivariate model
model <- reactive({
lm(regFormula(), data = datasetInput())
})
# create graphics
# data view
output$view <- renderTable({
head(datasetInput(), n = input$obs)
})
# summary statistics
output$summary <- renderPrint({
summary(cbind(datasetInput()[input$dv], datasetInput()[input$iv]))
})
# bivariate model
output$model <- renderPrint({
pander(summary(model()))
})
# residuals
output$residuals_hist <- renderPlot({
hist(model()$residuals, main = paste(input$dv, '~', input$iv), xlab = 'Residuals')
})
output$residuals_scatter <- renderPlot({
plot(model()$residuals ~ datasetInput()[,input$iv], xlab = input$iv, ylab = 'Residuals')
abline(h = 0, lty = 3)
})
output$residuals_qqline <- renderPlot({
qqnorm(model()$residuals)
qqline(model()$residuals)
})
})