I am building a Shiny app that helps user to create pie chart with ggplot2 on their own. Therefore, it would have a selector input for user to select variables from different dataframes. I was stuck with the input$ statements, it seemed that Shiny took the input$ with double quotes as a character, instead of a variable. Below is a simplified version of code, kindly let me know how to fix this. Thanks in advance!
library(ggplot2)
server <- function(input, output) {
output$var_selector <- renderUI({
selectInput('var_selector', 'Please select:', choices = names(mtcars))
})
output$pie_plot <- renderPlot({
ggplot(mtcars, aes(x = factor(1), fill = factor(input$var_selector))) + geom_bar(width = 1) + coord_polar(theta = "y")
})
output$text <- renderText({
print(input$var_selector)
})
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
h3('ggplot2 pie chart'),
uiOutput('var_selector')
),
mainPanel(
plotOutput('pie_plot')
)
)
)
shinyApp(ui = ui, server = server)
Related
I have imported the dataset = students for generating the reactive plots but proper plot is not generated .I am using ggplot for plots so could you
please tell me whats wrong in my code.
library(shiny)
library(ggplot2)
ui <- navbarPage("A SHINY APP!! ",
tabPanel("Plots",headerPanel("Different plots of data"),
sidebarLayout(
sidebarPanel(
selectInput("x.col","x.variable",choices=names(students))
),
mainPanel(plotOutput("histPlot")))
)
)
server <- function(input, output) {
plot <- reactive({ ggplot(students,aes(x=input$x.col))
})
output$histPlot <- renderPlot({
plot() + geom_histogram(stat = "count",bins = 30)
})
}
shinyApp(ui = ui, server = server
Try with get() function like the following:
ggplot(students, aes(x = get(input$x.col)))
I have tried to plot the graph separately using ggplot (outside the shiny app) and it plots well so I know the problem is not with my ggplot code but with how the inputs in the shiny app are entered into the renderplot({}) section. The inputs are the axes.
Code:
library(ggplot2)
library(shiny)
data1 <- mtcars
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "xaxis",
label = "Choose a Variable for the X-axis of the First Graph",
choices = colnames(data1)
),
selectInput(
inputId = "yaxis",
label = "Choose a Variable for the Y-axis of the First Graph",
choices = colnames(data1)
)
),
mainPanel(
plotOutput(outputId = "scatterplot"))
)
)
server <- function(input, output) {
output$scatterplot <- renderPlot({
req(input$xaxis)
req(input$yaxis)
ggplot(data1, aes(x = input$xaxis, y = input$yaxis))+geom_point()
})}
shinyApp(ui = ui, server = server)
Solution
You are passing a string to your aes, which does not work. You should try
server <- function(input, output) {
output$scatterplot <- renderPlot({
req(input$xaxis)
req(input$yaxis)
gggplot(data1, aes_string(x = paste0("`", input$xaxis, "`"),
y = paste0("`", input$yaxis, "`"))) + geom_point()
})
}
Explanation
aes expects the bare column name like in ggplot(mtcars, aes(am, vs)) + geom_point(). Note that we do not use quotatation marks " for am or vs (i.e. we are passing variable names and not strings). On the other hand input$xaxis returns a string. Thus, you have to use aes_string which is meant for working with strings rather than column names.
Update
Added backtricks to deal with non standard names.
I'm running into some issues in my work. To iullustrate the problem, I'm using the diamonds data as an example.
I made a function sca.plot. If the argument color.by=NULL, then make a scatter plot and color all points red. If color.by is some factor variable, make scatter plot and color points by the variable.
My question is when I make interactive scatter plot in shiny. How can I include the NULL option in selectinput widget, so that I can choose whether or not those points are colored by some variable?
If I include NULL in choices in selectinput, I got errors. Could not figure it out....
Thanks a lot in advance.
Below is my code:
library(ggplot2)
sca.plot <- function (color.by=NULL) {
if (is.null(color.by)) {
diamonds %>% ggplot(aes(x, y))+
geom_point (color='red')
} else {
color.by = sym(color.by)
diamonds %>% ggplot(aes_(~x, ~y, color=color.by))+
geom_point ()
}
}
sca.plot(color.by='clarity')
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput('colorby', label = h5(strong('Color By')),
choices = list('clarity', 'cut'),
selected = NULL)
),
mainPanel(
plotOutput('plot')
)
)
)
server <- function(input, output) {
output$plot <- renderPlot ({
sca.plot(color.by=input$colorby)
})
}
runApp(shinyApp(ui, server))
Here is the solution for you:
library(ggplot2)
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput('colorby', label = h5(strong('Color By')),
choices = list('NULL','clarity', 'cut'),
selected = NULL)
),
mainPanel(
plotOutput('plot')
)
)
)
server <- function(input, output) {
output$plot <- renderPlot ({
if(!input$colorby == 'NULL'){
ggplot(diamonds, aes_string(x="x",y="y", color=input$colorby)) +
geom_point()
}else{
ggplot(diamonds, aes(x=x,y=y)) +
geom_point(color='red')
}
})
}
shinyApp(ui = ui, server = server)
You can use NULL as an argument in selectInput but as a string --> 'NULL'
You actually do not need such a function as you wrote at the beginning of shiny app, you can easily use if...else... statement directly in renderPlot() to get the desired color of the geom_point().
Below is functioning code for a basic shiny app that allows the user to pick a column and then plots a ggplot::histogram() of the selected column:
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
titlePanel("ggplot"),
sidebarLayout(
sidebarPanel(
uiOutput("column_select")
),
mainPanel(plotOutput("plot"))
)
)
# Define server logic required to draw a histogram
server <- function(input, output){
dat <- reactive({iris})
output$column_select <- renderUI({selectInput("col", label = "column", choices = as.list(names(iris)), selected = "Sepal.Length")})
output$plot <- renderPlot({ggplot(dat(), aes_string(x = input$col)) +
geom_histogram()})
p <- ggplot(dat(), aes_string(x = input$col)) +
geom_histogram()
renderPlot
}
# Run the application
shinyApp(ui = ui, server = server)
I am not sure, however, why I am unable to remove the ggplot() function from within renderPlot() and still get the same result. I have tried:
p <- reactive({ggplot(dat(), aes_string(x = input$col)) +
geom_histogram()})
outputPlot <- renderPlot({p})
But this results in no plot being drawn.
I assume there is a simple fix to this, but thus far it escapes me.
I have a task where i need to build an rShiny app that allows the user to choose which kind of R plotting package is used in-order to display a plot.
Currently the only way i have gotten it to work (semi-decently) is using package specific functions for each package on the server side and using a series of conditional panels on the UI side.
However the problem is that when the user enters the page for the first time then all plots are initialized. Second problem is when the user changes some plot input values and after that chooses another package then the old plot will be displayed until a new plot is created.
Questions:
Is this the only available approach?
I feel that there must be a way to use reactive functions for the package selection?
I feel that it should be possible to use a single rShiny's htmlOutput (or something similar) in the ui and therefore not needing the switchPanel?
I have created a small app to demonstrate my current implementation and both problems:
server.R
library(shiny)
#library(devtools)
#install_github("ramnathv/rCharts")
library(rCharts)
shinyServer(function(input, output) {
names(iris) = gsub("\\.", "", names(iris))
#Render the Generic plot
output$GenericPlot <- renderPlot({
data = iris[0:input$variable,]
plot(data$SepalLength ~ data$SepalWidth)
})
#Render the Polychart plot
output$PolychartPlot <- renderChart({
plotData <- rPlot(SepalLength ~ SepalWidth, data = iris[0:input$variable,], color = 'Species', type = 'point')
plotData$addParams(dom = 'PolychartPlot')
return(plotData)
})
#Render the NDV3 plot
output$NDV3Plot <- renderChart({
plotData <- nPlot(SepalLength ~ SepalWidth, data = iris[0:input$variable,], group = 'Species', type = 'scatterChart')
plotData$addParams(dom = 'NDV3Plot')
return(plotData)
})
})
ui.R
library(shiny)
library(rCharts)
shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("lib", label = "Library:",
choices = list("Generic", "rCharts Polychart", "rCharts NDV3"),
selected = "Generic"
),
numericInput("variable", "Observations:",
min = 5,
max = 150,
value = 10
)
),
mainPanel(
conditionalPanel(
condition = "input.lib == 'Generic'",
h3("Generic plot"),
plotOutput("GenericPlot")
),
conditionalPanel(
condition = "input.lib == 'rCharts Polychart'",
h3("rCharts Polychart plot"),
showOutput("PolychartPlot", "polycharts")
),
conditionalPanel(
condition = "input.lib == 'rCharts NDV3'",
h3("rCharts NDV3 plot"),
showOutput("NDV3Plot", "nvd3")
)
)
)
))
The final version will use a different dataset and more charting packages. The provided code is more of a toy example, with most of the stuff stripped out.
Make a single part in the output part of the app that includes some logic based on the input. For example,
library(shiny)
library(ggplot2)
data(cars)
server <- function(input, output) {output$plot<- renderPlot({
if (input$lib == "base") {
p <- plot(cars$speed, cars$dist)
} else if (input$lib == "ggplot") {
p <- ggplot(cars, aes(x = speed, y = dist)) + geom_point()
}
p
})
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("lib", "Library: ", choices = list("base", "ggplot"),
selected = "base")
),
mainPanel(plotOutput("plot"))
)
)
shinyApp(ui = ui, server = server)
This provides one plot and as soon as I change the lib option it regenerates.
Found a solution to my problem. The solution is basically to use uiOutput() in the ui.R and move the plotOutput(), showOutput() methods to the server.R.
The solution based on iacobus code:
ui.R
library(shiny)
library(rCharts)
shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("lib", "Library: ", choices = list("base", "ggplot", "Polychart"),
selected = "base")
),
mainPanel(uiOutput("plot"))
)
))
server.R
library(shiny)
library(ggplot2)
library(rCharts)
data(cars)
server <- function(input, output) {
output$plot<- renderUI({
if (input$lib == "base") {
plotOutput("base")
} else if (input$lib == "ggplot") {
plotOutput("ggplot")
} else if (input$lib == "Polychart") {
showOutput("polychart", "polycharts")
}
})
output$base <- renderPlot({
plot(cars$speed, cars$dist)
})
output$ggplot <- renderPlot({
ggplot(cars, aes(x = speed, y = dist)) + geom_point()
})
output$polychart <- renderChart({
p <- rPlot(speed ~ dist, data = cars, type = "point")
p$addParams(dom = 'plot')
p
})
}
The difficulty arose for me, because i assumed that plotOutput(), showOutput() etc methods can only be used in the ui.R. This however is not the case.
EDIT:
It turned out that this was not enough for pollyCharts to work properly along with other rCharts packages.
instead i am using renderUI and rCharts $show to display the chart inline. The following link was helpful for me: https://github.com/ramnathv/rCharts/issues/373. In the ui i'm using htmlOutput