使用 Shiny 的 ggplot 中双重交互的问题
The problem with double interactivity in ggplot using Shiny
我正在尝试将两件事合并为 1 个小提琴情节。
在我的 Shiny 应用程序中,用户可以选择他想要在小提琴图中拥有的变量(X 变量)。
作为 Y 变量,我有年龄,用户可以选择范围:
如果我只是选择一个变量并保持完整的收入范围,那没有问题。
但是,当我想要一个不同的范围时,我得到一个错误。
为了让问题更明显:
- 这行得通,我可以更改 X 变量,并且适用于所有收入范围
- 如果我更改收入范围,我会收到错误消息
我认为问题的出现是因为 X 变量的范围不同。
我不知道如何以及在何处更改它以使其工作。
如果我放弃 X 交互性,它会起作用:
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)})
但我希望它保持互动。你有什么解决办法吗?
这是一个带有泰坦尼克号数据集的代码,显示了您可以复制粘贴的相同问题:
---
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)})
```
正如@Ben 所说;选择的行数不同。我对 Shiny 有点陌生,但为什么需要在反应部分对数据进行子集化?它不是必需的(稍后对其进行过滤)并且效率较低,因为每次更改所选变量时都会有效地对数据进行子集化(当然,在小数据集中不是大问题,但仍然..)
所以我建议:
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
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")
)
)
)
定义服务器逻辑
服务器 <- 函数(输入,输出){
数据(虹膜)
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, 服务器 = 服务器)
我正在尝试将两件事合并为 1 个小提琴情节。 在我的 Shiny 应用程序中,用户可以选择他想要在小提琴图中拥有的变量(X 变量)。 作为 Y 变量,我有年龄,用户可以选择范围:
如果我只是选择一个变量并保持完整的收入范围,那没有问题。 但是,当我想要一个不同的范围时,我得到一个错误。
为了让问题更明显:
- 这行得通,我可以更改 X 变量,并且适用于所有收入范围
- 如果我更改收入范围,我会收到错误消息
我认为问题的出现是因为 X 变量的范围不同。 我不知道如何以及在何处更改它以使其工作。
如果我放弃 X 交互性,它会起作用:
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)})
但我希望它保持互动。你有什么解决办法吗? 这是一个带有泰坦尼克号数据集的代码,显示了您可以复制粘贴的相同问题:
---
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)})
```
正如@Ben 所说;选择的行数不同。我对 Shiny 有点陌生,但为什么需要在反应部分对数据进行子集化?它不是必需的(稍后对其进行过滤)并且效率较低,因为每次更改所选变量时都会有效地对数据进行子集化(当然,在小数据集中不是大问题,但仍然..)
所以我建议:
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
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")
)
)
)
定义服务器逻辑
服务器 <- 函数(输入,输出){ 数据(虹膜)
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, 服务器 = 服务器)