使用 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, 服务器 = 服务器)