首页 文章

Shiny&ggplot:ggplot的aes()映射语句中无法识别的数字变量

提问于
浏览
2

GOAL: 创建一个直方图,接受用于bin计数的用户输入,并用曲线覆盖它以适合分布 . 绘制的数据是一个人切割cookie所需的时间 .

KEY FUNCTIONS:

geom_histogram(aes(y = ...count ..),bins = input $ binCount) - 该语句创建一个频率图,其中包含用户指定的二进制数 .

geom_density(aes(y =(.. density ...)(N)(binWidth))) - 此语句应该创建适合分布的曲线 . "N"是数据点的总数(20),"binWidth"是每个bin的宽度(默认值= 5),根据用户指定的bin数量而变化 . 可以找到对这种转换背后的数学的完整解释here .

PROBLEM: "geom_density()"函数中的"aes()"映射语句无法识别先前在"RenderPlot"块中创建的变量"N"或"binWidth" .

CODE: 以下代码可立即运行 . 第84行将导致错误 . 如果您想查看David或Sharon的结果(使用默认的binCount = 5),那么您可以取消注释第85或86行 .

SIMILAR ISSUES: 我发现了一些处理类似ggplot问题的帖子,例如this post,但它们主要处理使用"aes_string()"将字符串传递给映射语句,而我使用的是数字变量 .

Thanks for any help you can provide!

#
# Cookie Cutting Analytics
#
# Author: Cody
# Date:   10/16/2017
# Descr:  An application to analyze David and Sharon's cookie cutting efficiency.
#

# Libraries -----------------------------------------------------------
suppressWarnings(library(dplyr))
suppressWarnings(library(ggplot2))
suppressWarnings(library(shiny))


# User Interface ------------------------------------------------------
ui <- fluidPage(

  # App Title
  titlePanel("Cookie Cutting Analytics"),

  # Sidebar layout
  sidebarLayout(

    # Sidebar panel for Input
    sidebarPanel(

      # Input: Proc Name Dropdown
      selectInput("cutterPerson", "Cookie Cutter:",
                  c("David", "Sharon")),

      # Input: Histogram Bin Count Slider
      sliderInput("binCount", "Number of Bins:",
                  min = 1,
                  max = 10,
                  value = 5)

    ),

    # Main panel for displaying outputs
    mainPanel(

      tabsetPanel(type = "tabs",
                  tabPanel("Plots",
                           br(),
                           plotOutput("histogram"),
                           br(),
                           plotOutput("boxPlot")),
                  tabPanel("Stats", verbatimTextOutput("summary")),
                  tabPanel("Data", tableOutput("table"))
      )

    )

  )
)


# Server Logic --------------------------------------------------------
server <- function(input, output) {

  # Reactive Expression: Cookie Data
  cookieData.df <- reactive ({
    person <- c("David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon")
    cutTime <- c(5,10,8,12,6,9,8,8,4,15,9,14,5,9,7,12,6,13,8,11,6,12,6,10,8,13,9,8,5,11,4,13,7,10,5,12,6,10,5,15)
    data.frame(person, cutTime)
  })

  # Reactive Expression: Person Cutting
  cutterName <- reactive({
    input$cutterPerson
  })

  # Reactive Expression: Filtered Data
  filteredData.df <- reactive({
    cookieData.df() %>% select(person, cutTime) %>% filter(person == input$cutterPerson)
  })

  # Output: Histogram
  output$histogram <- renderPlot({
    N <- nrow(filteredData.df())
    binWidth = (max(filteredData.df()$cutTime)-min(filteredData.df()$cutTime) / input$binCount)
    ggplot(filteredData.df(), aes(cutTime)) + 
      geom_histogram(aes(y = ..count..), bins = input$binCount) +
      geom_density(aes(y = ..density..* N * binWidth), color = "red") + # Error: Does not recognize "N" or "binWidth"
      #geom_density(aes(y = ..density.. * 20 * 1), color = "red") + # David Curve: N = 10, binWidth = (max(cutTime)-min(cutTime))/binCount = (9-4)/5 = 1
      #geom_density(aes(y = ..density.. * 20 * 1.4), color = "red") + # Sharon Curve: N = 10, binWidth = (max(cutTime)-min(cutTime))/binCount = (15-8)/5 = 1.4
      labs(title = "Histogram of Cookie Cut Times", x = "Cut Duration (s)", y = "Frequency") +
      theme(plot.title = element_text(size = 25, face = "bold"),
            axis.title = element_text(size = 15, face = "bold"))
  })


  # Reactive Expression: (N) Filtered Data
  N <- reactive({
    nrow(filteredData.df())
  })

  # Reactive Expression: (binWidth) Filtered Data
  binWidth <- reactive({
    (max(filteredData.df()$cutTime) - min(filteredData.df()$cutTime)) / input$binCount
  })

}


shinyApp(ui, server)

2 回答

  • 4

    考虑更简单的例子

    # works
    ggplot(iris, aes(Sepal.Width)) + geom_density(aes(y=..density.. * 5))
    # doesn't work
    N <- 5
    ggplot(iris, aes(Sepal.Width)) + geom_density(aes(y=..density.. * N))
    

    对于为您进行计算的ggplot图层,他们需要创建自己的变量,当他们这样做时,他们无法访问他们没有创建的值(至少它是当前实现的方式) .

    所以你有两个我能想到的选择:1)自己计算密度,或2)动态构建表达式,使其中没有其他未评估的变量 .

    对于选项一,可能看起来像

    dens <- density(iris$Sepal.Width, kernel = "gaussian") #geom_density equivalent
    N <- 5
    ggplot(iris, aes(Sepal.Width)) +
        geom_histogram() + 
        geom_area(aes(x, y*N), data=data.frame(x=dens$x, y=dens$y))
    

    对于选项2,您可以这样做

    N <- 5
    dens_map <- eval(bquote(aes(y = ..density..* .(N))))
    ggplot(iris, aes(Sepal.Width)) +
        geom_histogram() + 
        geom_density(dens_map)
    

    它基本上将变量名称扩展为它的数值 .

  • 0

    虽然之前的答案已经足够好了,但是 stat_density 允许我们提取我们可以进行算术运算并构建图层的密度值,只是想分享这种方法 .

    if(interactive()){
      #
      # Cookie Cutting Analytics
      #
      # Author: Cody
      # Date:   10/16/2017
      # Descr:  An application to analyze David and Sharon's cookie cutting efficiency.
      #
    
      # Libraries -----------------------------------------------------------
      suppressWarnings(library(dplyr))
      suppressWarnings(library(ggplot2))
      suppressWarnings(library(shiny))
    
    
      # User Interface ------------------------------------------------------
      ui <- fluidPage(
    
        # App Title
        titlePanel("Cookie Cutting Analytics"),
    
        # Sidebar layout
        sidebarLayout(
    
          # Sidebar panel for Input
          sidebarPanel(
    
            # Input: Proc Name Dropdown
            selectInput("cutterPerson", "Cookie Cutter:",
                        c("David", "Sharon")),
    
            # Input: Histogram Bin Count Slider
            sliderInput("binCount", "Number of Bins:",
                        min = 1,
                        max = 10,
                        value = 5)
    
          ),
    
          # Main panel for displaying outputs
          mainPanel(
    
            tabsetPanel(type = "tabs",
                        tabPanel("Plots",
                                 br(),
                                 plotOutput("histogram"),
                                 br(),
                                 plotOutput("boxPlot")),
                        tabPanel("Stats", verbatimTextOutput("summary")),
                        tabPanel("Data", tableOutput("table"))
            )
    
          )
    
        )
      )
    
    
      # Server Logic --------------------------------------------------------
      server <- function(input, output) {
    
        # Reactive Expression: Cookie Data
        cookieData.df <- reactive ({
          person <- c("David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon","David","Sharon")
          cutTime <- c(5,10,8,12,6,9,8,8,4,15,9,14,5,9,7,12,6,13,8,11,6,12,6,10,8,13,9,8,5,11,4,13,7,10,5,12,6,10,5,15)
          data.frame(person, cutTime)
        })
    
        # Reactive Expression: Person Cutting
        cutterName <- reactive({
          input$cutterPerson
        })
    
        # Reactive Expression: Filtered Data
        filteredData.df <- reactive({
          cookieData.df() %>% select(person, cutTime) %>% filter(person == input$cutterPerson)
        })
    
        # Output: Histogram
        output$histogram <- renderPlot({
          #N <- nrow(filteredData.df())
          #binWidth = (max(filteredData.df()$cutTime)-min(filteredData.df()$cutTime) / input$binCount)
          #N <- 20
          #binWidth = 1
          n <- ggplot(filteredData.df(), aes(cutTime))
    
          n.data <- ggplot_build (n + stat_density(aes(y =..density..)))[['data']][[1]]
    
          n.data$y <- n.data$y * N() * binWidth()
    
          #n.data$y <- n.data$y * 20 * 1
    
          n + geom_histogram(aes(y = ..count..), bins = input$binCount) + 
    
            geom_line(data = n.data, aes(x = x, y = y), color = 'red') + 
    
    
            #geom_density(aes(y = ..density.. * 20 * 1), color = "red") + # David Curve: N = 10, binWidth = (max(cutTime)-min(cutTime))/binCount = (9-4)/5 = 1
            #geom_density(aes(y = ..density.. * 20 * 1.4), color = "red") + # Sharon Curve: N = 10, binWidth = (max(cutTime)-min(cutTime))/binCount = (15-8)/5 = 1.4
            labs(title = "Histogram of Cookie Cut Times", x = "Cut Duration (s)", y = "Frequency") +
            theme(plot.title = element_text(size = 25, face = "bold"),
                  axis.title = element_text(size = 15, face = "bold"))
    
          #m <- print(m)
    
        })
    
    
        # Reactive Expression: (N) Filtered Data
        N <- reactive({
          nrow(filteredData.df())
        })
    
        # Reactive Expression: (binWidth) Filtered Data
        binWidth <- reactive({
          (max(filteredData.df()$cutTime) - min(filteredData.df()$cutTime)) / input$binCount
        })
    
      }
    
    
      shinyApp(ui, server)
    }
    

    截图:

    enter image description here

相关问题