参数化的ggplot2直方图/密度aes函数找不到对象

时间:2015-06-10 16:19:25

标签: r ggplot2

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

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

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

# 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..))
}

histogram/density with count as y axis and hardcoded binwidth

我的第一个失败天真地尝试在 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可以参数化(例如,用于操作)

3 个答案:

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

答案 1 :(得分:1)

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

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]])

答案 2 :(得分: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'))
    }