I am trying to combine two things into 1 violin plot. In my Shiny app user can choose variable he want to have in violin plot (X variable). As a Y variable I have age which can have range chosen by user:
There is no problem if I just pick a variable and stay with full range of income. However, when I want to have a different range I get an error.
To show the problem more visible:
- this works ok, I can change the X variable and it is fine with the full range of income
I think that the problem appears because the X variable has different range. I don't know how and where to change it to make it work.
If I drop the X interactivity it works:
renderPlot({
data %>%
filter(
between(Age, input$income[1], input$income[2])) %>%
ggplot(aes(x=Sex, y=Age)) +
geom_violin(aes(fill=Sex), trim=FALSE) +
geom_boxplot(width=0.3)+
stat_summary(fun=mean, geom="point", shape=20, size=5)+
ggtitle(input$var)})
But I want it to stay interactive. Do you have any solution for that? Here is a code with titanic dataset showing the same problem which you can copy-paste:
---
title: "dataset"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
runtime: shiny
---
```{r global, include=FALSE}
#dataset, libraries and other global things
library(flexdashboard)
library(ggplot2)
library(tidyverse)
library(dplyr)
library(titanic)
data("titanic_train")
data<-na.omit(titanic_train)
```
Dashboard {data-orientation=rows}
=====================================
Inputs {.sidebar}
-------------------------------------
**Age by:**
```{r plot-option}
selectInput("var", label = "Please choose variable:",
choices = names(subset(data, select=c(Sex ,Pclass, SibSp))))
sliderInput("income", HTML("Income interval:"),
min = min(data$Age), max = max(data$Age), value = c(min(data$Age), max(data$Age)), step =1)
```
Row
-------------------------------------
### Age by: {data-width=450}
```{r}
selected <- reactive({ data[, c(input$var)] })
renderPlot({
data %>%
filter(
between(Age, input$income[1], input$income[2])) %>%
ggplot(aes(x=selected(), y=Age)) +
geom_violin(aes(fill=input$var), trim=FALSE) +
geom_boxplot(width=0.3)+
stat_summary(fun=mean, geom="point", shape=20, size=5)+
ggtitle(input$var)})
```
As @Ben says; there is a difference in the number of rows selected. I'm somewhat new with Shiny, but why do you need to subset the data in the reactive part? It's not needed (you filter it later on) and it's less efficient since you're effectively subsetting your data every time you change the selected variable (granted, not a big problem in a small dataset, but still..)
So I suggest:
renderPlot({
data %>%
filter(
between(MonthlyIncome, input$income[1], input$income[2])) %>%
ggplot(aes_string(x= input$var, y=data$MonthlyIncome)) +
geom_violin(aes(fill=input$var), trim=FALSE) +
geom_boxplot(width=0.3)+
stat_summary(fun=mean, geom="point", shape=20, size=5)+
ggtitle(input$var)})
ui <- fluidPage(
# Application title
titlePanel("Iris"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Variables","Choose a Variable",
choices = c(colnames(iris)),
selected = "Species"),
sliderInput("PetalLength", "Length Interval",
min = 0.1, max = 10, value = c(0.5, 7.5), step = 0.1)
)
,
# Show a plot of the generated distribution
mainPanel(
plotOutput("irisPlot")
)
)
)
server <- function(input, output) { data(iris)
output$irisPlot <- renderPlot({
iris_data <- filter(iris, between(Petal.Length, input$PetalLength[1], input$PetalLength[2]))
ggplot(iris_data, aes_string(x= input$Variables, y=iris_data$Petal.Length)) +
geom_violin(aes(fill=input$Variables), trim=FALSE) +
geom_boxplot(width=0.3)+
stat_summary(fun=mean, geom="point", shape=20, size=5)+
ggtitle(input$Variables)})
}
shinyApp(ui = ui, server = server)