【问题标题】:Parameterized ggplot2 histogram/density aes function cannot find object参数化 ggplot2 直方图/密度 aes 函数找不到对象
【发布时间】:2015-08-26 00:53:03
【问题描述】:

我创建了一个直方图/密度图函数,我希望 y 轴为 count 而不是密度,但在参数化其 binwidth 时遇到问题。

我使用基于http://docs.ggplot2.org/current/geom_histogram.html 的示例来说明我的尝试。

这是成功的 plotMovies1 函数。我按照引用的url 使 y 轴 ..count.. 而不是 ..density.. 请注意,它在两个地方使用了硬编码的 .5 binwidth ,这就是我要参数化的...

# I want y axis as count, rather than density, and followed
# https://stat.ethz.ch/pipermail/r-help/2011-June/280588.html
plotMovies1 <- function() {
  m <- ggplot(movies, aes(x = rating))
  m <- m + geom_histogram(binwidth = .5)
  m <- m + geom_density(aes(y = .5 * ..count..))
}

我第一次失败天真地尝试在 plotMovies2 中的本地 bw 中参数化 binwidth ...

# Failed first attempt to parameterize binwidth
plotMovies2 <- function() {
  bw <- .5
  m <- ggplot(movies, aes(x = rating))
  m <- m + geom_histogram(binwidth = bw)
# Error in eval(expr, envir, enclos) : object 'bw' not found 
  m <- m + geom_density(aes(y = bw * ..count..))
}
> print(plotMovies2())
Error in eval(expr, envir, enclos) : object 'bw' not found

我在https://github.com/hadley/ggplot2/issues/743 看到关于将本地环境传递给 ggplot 中的 aes 的讨论,但 plotMovies3 也以同样的方式失败,未能找到 bw 对象。 ..

# Failed second attempt to parameterize binwidth, even after establishing
# aes environment, per https://github.com/hadley/ggplot2/issues/743
plotMovies3 <- function() {
  bw <- .5
  m <- ggplot(movies, aes(x = rating), environment = environment())
  m <- m + geom_histogram(binwidth = bw)
# Error in eval(expr, envir, enclos) : object 'bw' not found 
  m <- m + geom_density(aes(y = bw * ..count..))
}
> print(plotMovies3())
Error in eval(expr, envir, enclos) : object 'bw' not found

我终于尝试设置一个全局,但它仍然未能找到对象...

# Failed third attempt using global binwidth
global_bw <<- .5
plotMovies4 <- function() {
  m <- ggplot(movies, aes(x = rating), environment = environment())
  m <- m + geom_histogram(binwidth = global_bw)
# Error in eval(expr, envir, enclos) : object 'global_bw' not found 
  m <- m + geom_density(aes(y = global_bw * ..count..))
}
> print(plotMovies4())
Error in eval(expr, envir, enclos) : object 'global_bw' not found

鉴于 plotMovies3 和 plotMovies4,我猜这不是一个简单的环境问题。谁能阐明我如何解决这个问题?同样,我的目标是能够创建一个直方图/密度图函数,其中

  1. 它的 y 轴是计数而不是密度,并且
  2. 它的 binwidth 可以参数化(例如,用于操作)

【问题讨论】:

  • 小提示:运行global_bw &lt;&lt;- 0.5 绝不会创建“全局”变量。在最后一个示例中使用&lt;- 将具有相同的效果。 &lt;&lt;- 只是一种在不同范围内进行变量赋值的方法。如果您在函数中包含该行,您将在全局环境中创建一个对象,而不是在函数中创建本地对象。
  • 您的函数不返回任何对象。如果你把return(m)放在最后,它可能会让事情运行得更顺利。
  • 一个最小的例子是bw= 0.5; m &lt;- ggplot(movies, aes(x = rating)); m + geom_density(aes(y = bw * ..count..))
  • 潜在兴趣(昨天提交):github.com/hadley/ggplot2/commit/…
  • @joran,感谢提交链接似乎指向github.com/hadley/ggplot2/issues/743

标签: r ggplot2


【解决方案1】:

这是对 mts 的跟进。它旨在作为一个长评论:首先,数据集是通过加载library("ggplot2movies") 获得的。其次,循环遍历binw 的多个值以生成一系列要一起使用的数字可能是有意义的,例如动画。所以下面的代码所做的只是为了这个目的将mts的代码放入一个循环中。确实是微不足道的贡献。

    ### Data
    library("ggplot2movies")

    ### Histograms
    ggplotMovieHistogram <- function(binw = 0.5) {
        require('ggplot2movies')
        p <- ggplot(movies, aes(x = rating)) + 
            geom_histogram(binwidth = binw)
        wa <- density(x = movies$rating, bw = binw)
        wa <- as.data.frame(cbind(xvals = wa$x, yvals = wa$y * wa$n * binw))
        p <- p + geom_point(data = wa, aes(x = xvals, y = yvals))
        return(p)
    }

    ggsaveMovieHistogram <- function(binw = 0.5, file = 'test.pdf') {
        pdf(file, width = 8, height = 8)
            print(ggplotMovieHistogram(binw = binw))
        dev.off()
    }

    for(i in seq(0.2, 0.8, by = 0.2)) {
        ggsaveMovieHistogram(binw = i, 
                    file = paste0('ggplot-barchart-loop-histogram-', 
                                  format(i, decimal.mark = '-'), 
                                  '.pdf'))
    }


    ### Densities
    library("ggplot2movies")
    ggplotMovieDensity <- function(binw = 0.5) {
        require('ggplot2movies')
        p <- ggplot(movies, aes(x = rating)) + 
            geom_density(aes(y = 0.5 * ..count..))
        wa <- density(x = movies$rating, bw = binw)
        wa <- as.data.frame(cbind(xvals = wa$x, yvals = wa$y * wa$n * binw))
        p <- p + geom_point(data = wa, aes(x = xvals, y = yvals))
        return(p)
    }

    ggsaveMovieDensity <- function(binw = 0.5, file = 'test.pdf') {
        pdf(file, width = 8, height = 8)
            print(ggplotMovieDensity(binw = binw))
        dev.off()
    }

    for(i in seq(0.2, 0.8, by = 0.2)) {
        ggsaveMovieDensity(binw = i, 
                    file = paste0('ggplot-barchart-loop-density-', 
                                  format(i, decimal.mark = '-'), 
                                  '.pdf'))
    }

【讨论】:

    【解决方案2】:

    另一种方法是使用带有 aes_string 的预定义 bin。然后可以通过具有可变 binwidth 的循环创建直方图:

    bins <<- list()
    bins[["Variable1"]] <- 2
    bins[["Variable2"]] <- 0.5
    bins[["Variable3"]] <- 1
    print(ggplot(movies, aes(x = rating))+
    aes_string(x = "rating", y=paste("..density..*",bins[[i]],sep="")), na.rm=TRUE, position='dodge', binwidth=bins[[i]])
    

    【讨论】:

      【解决方案3】:

      绝不漂亮,但如果您需要解决方法,您可以使用常规的density 函数

      plotMovies5 <- function(binw=0.5) {
        m <- ggplot(movies, aes(x = rating))
        m <- m + geom_histogram(binwidth = binw)
        wa <- density(x=movies$rating, bw = binw)
        wa <- as.data.frame(cbind(xvals = wa$x, yvals = wa$y * wa$n * binw))
        m <- m + geom_point(data = wa, aes(x = xvals, y = yvals))
      }
      print(plotMovies5(binw=0.25))
      

      请注意,您仍然需要对变量进行一些修改,因为密度估计值并不完全相等,如下所示:

      binw = 0.5
      m <- ggplot(movies, aes(x = rating))
      m <- m + geom_density(aes(y = 0.5 * ..count..))
      wa <- density(x=movies$rating, bw = binw)
      wa <- as.data.frame(cbind(xvals = wa$x, yvals = wa$y * wa$n * binw))
      m <- m + geom_point(data = wa, aes(x = xvals, y = yvals))
      m
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多