【问题标题】:Cannot add ggproto objects together无法将 ggproto 对象添加在一起
【发布时间】:2020-12-10 23:02:50
【问题描述】:

我目前正在开发一款 Rshiny 应用程序。我必须用几个选择输入和一个复选框输入制作多个箱线图。我几乎完成了我的任务,现在我只需要完成它,以便每次更改所选物种时,比例保持不变(当然,除非输入了其他变量)。

我的代码如下所示:

library(shiny)
library(palmerpenguins)
library(dplyr)
library(ggplot2)

data <- na.omit(penguins)

colnames(data) <- c("Species",
                    "Island",
                    "Bill Length (mm)",
                    "Bill Depth (mm)", 
                    "Flipper Length (mm)",
                    "Body Mass (g)",
                    "Sex",
                    "Year")

data.numeric <- data[, c(3:6, 8)]

data.categorical <- data[, c(1,7)]


ui <- fluidPage(
  headerPanel("Penguin boxplots"),
  selectInput("ycol", 
              "Numeric Variable", 
              names(data.numeric),
              selected = names(data.numeric)[3]),
  selectInput("xcol",
              "Categorical Variable",
              names(data.categorical),
              selected = names(data.categorical)[2]),
  checkboxInput("split",
                "Split levels by Island",
                value = FALSE),
  selectInput("species",
              "Species Type",
              c("Unspecified", levels(data$Species))),
  mainPanel(
    plotOutput("plot1")
  ))






# 4. Use a select input to allow the user to view separate plotting 
# panels for each species, with each plot panel on the same scale.


server <- function(input, output){
  output$plot1 <- renderPlot({
    par(mar = c(5, 4.1, 0, 1))
    
    if (input$species == "Unspecified"){
      
      
      
      
      if (input$split) {
        ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]], fill = Island)) +
          geom_boxplot(na.rm = TRUE) +
          
          if (input$ycol == "Bill Length (mm)"){
              coord_cartesian(ylim = c(30, 60)) 
          } else if (input$ycol == "Bill Depth (mm)"){
            coord_cartesian(ylim = c(12.5, 21.5)) 
          } else if (input$ycol == "Flipper Length(mm)"){
            coord_cartesian(ylim = c(170, 232)) 
          } else if (input$ycol == "Body Mass (g)"){
            coord_cartesian(ylim = c(2500, 6500))
          } else if (input$ycol == "Year"){
            coord_cartesian(ylim = c(2006, 2009))
          } +
          xlab(input$xcol) +
          ylab(input$ycol) + 
          scale_x_discrete(labels = c("Female", "Male")) +
          theme(text = element_text(size = 15))
        
      } else {
        ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]])) +
          geom_boxplot(na.rm = TRUE) +
          if (input$ycol == "Bill Length (mm)"){
            coord_cartesian(ylim = c(30, 60)) 
          } else if (input$ycol == "Bill Depth (mm)"){
            coord_cartesian(ylim = c(12.5, 21.5)) 
          } else if (input$ycol == "Flipper Length(mm)"){
            coord_cartesian(ylim = c(170, 232)) 
          } else if (input$ycol == "Body Mass (g)"){
            coord_cartesian(ylim = c(2500, 6500))
          } else if (input$ycol == "Year"){
            coord_cartesian(ylim = c(2006, 2009))
          } +
          xlab(input$xcol) +
          ylab(input$ycol) +
          theme(text = element_text(size = 15))
      }
      
      
      
      
      
      
      
    } else {
      
      
      
      
      
      data <- data %>%
        filter(data$Species == input$species)
      if (input$split) {
        ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]], fill = Island)) +
          geom_boxplot(na.rm = TRUE) +
          xlab(input$xcol) +
          ylab(input$ycol) + 
          scale_x_discrete(labels = c("Female", "Male")) +
          theme(text = element_text(size = 15))
        
      } else {
        ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]])) +
          geom_boxplot(na.rm = TRUE) +
          xlab(input$xcol) +
          ylab(input$ycol) +
          theme(text = element_text(size = 15))
      }
    }
    
    
  })
}

















shinyApp(ui = ui, server = server)

当我运行包含else if (input$ycol == "Year"){ coord_cartesian(ylim = c(2006, 2009))} 的行时出现以下错误:无法将 ggproto 对象添加在一起。您是否忘记将此对象添加到 ggplot 对象中?

我不确定我在哪里出错了,或者我只是忽略了某种语法错误。

附言代码尚未完成 - 我仍然需要添加更多代码来控制物种不是“未指定”时的比例,但在弄清楚这一点之前我不会这样做。

【问题讨论】:

  • 在最后一个 ggplot 语句中尝试 else 而不是 if else
  • 看到我之前也这么认为并尝试过,但它不起作用。我已经把它改回来了,它仍然无法正常工作。仍然说同样的错误。这是现在的代码行:else { coord_cartesian(ylim = c(2006, 2009))}

标签: r if-statement ggplot2 shiny


【解决方案1】:

您可以通过创建一个返回所需coord_cartesian 语句的函数来简化事情。然后可以使用 + 将函数添加到 ggplot 链中,就像在通常的 ggplot 工作流程中一样。

下面的示例使用您示例中的硬编码选项。但是,如果您可以提供有关如何选择这些范围的更多信息,则可以以更自动化的方式获取 y 范围,而不必对每种可能的情况进行显式硬编码。

在下面的示例中,case_when 语句返回适当的ylim 值以提供给coord_cartesian。如果input$ycol 不匹配任何选项,case_when 将返回ylim=c(NA,NA),这将导致 ggplot 保持默认轴范围。

# I've included only 3 choices. Add in as many additional choices as needed.
coord_fnc = function(x=input$ycol) {
  ylim = dplyr::case_when(
      x=="Bill Length (mm)" ~ c(30,60),
      x=="Flipper Length(mm)" ~ c(170, 232),
      x=="Bill Depth (mm)" ~ c(12.5,21.5)
  )
  coord_cartesian(ylim=ylim)
}


ggplot(data, aes(x = data[[input$xcol]], y = data[[input$ycol]], fill = Island)) +
  geom_boxplot(na.rm = TRUE) +
  coord_fnc() +
  xlab(input$xcol) +
  ylab(input$ycol) +
  theme(text = element_text(size = 15))

用内置的mtcars数据框试试吧:

ggplot(mtcars, aes(hp, mpg)) + 
  geom_point() + 
  coord_fnc("Bill Length (mm)")

虽然if else 语句的字符串需要大量代码,但这种方法可以工作,我不确定您为什么会收到错误(可能是代码的其他部分)。例如,这有效:

input = list(ycol = "Year")

ggplot(mtcars, aes(hp, mpg)) + 
  geom_point() + 
  if (input$ycol == "Bill Length (mm)"){
    coord_cartesian(ylim = c(30, 60)) 
  } else if (input$ycol == "Bill Depth (mm)"){
    coord_cartesian(ylim = c(12.5, 21.5)) 
  } else if (input$ycol == "Flipper Length(mm)"){
    coord_cartesian(ylim = c(170, 232)) 
  } else if (input$ycol == "Body Mass (g)"){
    coord_cartesian(ylim = c(2500, 6500))
  } else if (input$ycol == "Year"){
    coord_cartesian(ylim = c(2006, 2009))
  }

【讨论】:

  • 非常感谢。我试过你的第一种方法,效果很好!
猜你喜欢
  • 1970-01-01
  • 2021-10-06
  • 2011-08-22
  • 1970-01-01
  • 2020-10-17
  • 2020-11-21
  • 1970-01-01
相关资源
最近更新 更多