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

时间:2017-10-16 13:45:27

标签: r ggplot2 shiny

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

关键功能:

geom_histogram(aes(y = ..count ..),bins = input $ binCount) - 此语句使用用户指定的箱数创建频率图。

geom_density(a =(..density ..)(N)(binWidth))) - 此语句假设以创建适合的曲线分配。 “N”是数据点的总数(20),“binWidth”是每个bin的宽度(默认值= 5),其根据用户指定的bin的数量而变化。可以找到对此转换背后的数学的完整解释here

问题:“geom_density()”函数中的“aes()”映射语句无法识别先前在“RenderPlot”中创建的变量“N”或“binWidth”块。

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

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

感谢您提供的任何帮助!

#
# 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 个答案:

答案 0 :(得分: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)

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

答案 1 :(得分: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