我正在使用ggplot 2.1.0来绘制直方图,我对直方图箱有意想不到的行为。 我在这里给出了一个左闭合箱的例子(即[0,0.1 [],其宽度为0.1。
mydf <- data.frame(myvar=c(-1,-0.5,-0.4,-0.1,-0.1,0.05,0.1,0.1,0.25,0.5,1))
myplot <- ggplot(mydf, aes(myvar)) + geom_histogram(aes(y=..count..),binwidth = 0.1, boundary=0.1,closed="left")
myplot
ggplot_build(myplot)$data[[1]]
在这个例子中,人们可能期望值-0.4在bin [-0.4,-0.3 [,但它在([神秘地])在bin [-0.5,-0.4 [。值-0.1的值相同,它落在[-0.2,-0.1 [而不是[-0.1,0 [... etc。
]这里有什么东西我不完全理解(尤其是新的“中心”和“边界”参数)?或者ggplot2在那里做了奇怪的事情?
提前致谢, 最好的祝福, 阿诺
答案 0 :(得分:5)
修改:最近发布的ggplot2
版本修复了下述问题。
您的问题是可重现的,似乎是由舍入错误引起的,正如Roland的评论所示。在这一点上,这看起来像版本ggplot2_2.0.0
中引入的错误。我在下面推测它的起源,但首先让我提出一个基于boundary
选项的解决方法。
<强>问题强>:
df <- data.frame(var = seq(-100,100,10)/100)
as.list(df) # check the data
$var
[1] -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2
[10] -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
[19] 0.8 0.9 1.0
library("ggplot2")
p <- ggplot(data = df, aes(x = var)) +
geom_histogram(aes(y = ..count..),
binwidth = 0.1,
boundary = 0.1,
closed = "left")
p
解决方案
调整boundary
参数。在这个例子中,设置低于1,比如0.99,可以工作。您的用例也应该适合调整。
ggplot(data = df, aes(x = var)) +
geom_histogram(aes(y = ..count..),
binwidth = 0.05,
boundary = 0.99,
closed = "left")
(为了更好的视觉效果,我使binwidth更窄)
另一种解决方法是引入自己的模糊性,例如:将数据乘以1加略小于机器零点(参见下面的eps
)。在ggplot2
中,模糊性乘以1e-7(早期版本)或1e-8(更高版本)。
原因:
问题在ncount
:
str(ggplot_build(p)$data[[1]])
## 'data.frame': 20 obs. of 17 variables:
## $ y : num 1 1 1 1 1 2 1 1 1 0 ...
## $ count : num 1 1 1 1 1 2 1 1 1 0 ...
## $ x : num -0.95 -0.85 -0.75 -0.65 -0.55 -0.45 -0.35 -0.25 -0.15 -0.05 ...
## $ xmin : num -1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 ...
## $ xmax : num -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 ...
## $ density : num 0.476 0.476 0.476 0.476 0.476 ...
## $ ncount : num 0.5 0.5 0.5 0.5 0.5 1 0.5 0.5 0.5 0 ...
## $ ndensity: num 1.05 1.05 1.05 1.05 1.05 2.1 1.05 1.05 1.05 0 ...
## $ PANEL : int 1 1 1 1 1 1 1 1 1 1 ...
## $ group : int -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 ...
## $ ymin : num 0 0 0 0 0 0 0 0 0 0 ...
## $ ymax : num 1 1 1 1 1 2 1 1 1 0 ...
## $ colour : logi NA NA NA NA NA NA ...
## $ fill : chr "grey35" "grey35" "grey35" "grey35" ...
## $ size : num 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...
## $ linetype: num 1 1 1 1 1 1 1 1 1 1 ...
## $ alpha : logi NA NA NA NA NA NA ...
ggplot_build(p)$data[[1]]$ncount
## [1] 0.5 0.5 0.5 0.5 0.5 1.0 0.5 0.5 0.5 0.0 1.0 0.5
## [13] 0.5 0.5 0.0 1.0 0.5 0.0 1.0 0.5
ROUNDING ERRORS?
看起来像:
df <- data.frame(var = as.integer(seq(-100,100,10)))
# eps <- 1.000000000000001 # on my system
eps <- 1+10*.Machine$double.eps
p <- ggplot(data = df, aes(x = eps*var/100)) +
geom_histogram(aes(y = ..count..),
binwidth = 0.05,
closed = "left")
p
(我已完全删除了boundary
选项)
此行为出现在ggplot2_1.0.1
之后的某个时间。查看源代码,例如bin.R
中的stat-bin.r
和https://github.com/hadley/ggplot2/blob/master/R
以及跟踪count
的计算会导致函数bin_vector()
,其中包含以下几行:
bin_vector <- function(x, bins, weight = NULL, pad = FALSE) {
... STUFF HERE I HAVE DELETED FOR CLARITY ...
cut(x, bins$breaks, right = bins$right_closed,
include.lowest = TRUE)
... STUFF HERE I HAVE DELETED FOR CLARITY ...
}
通过将这些功能的当前版本与旧版本进行比较,您应该能够找到不同行为的原因......继续......
加强调试
通过"patching"
bin_vector
功能并将输出打印到屏幕,显示:
bins$fuzzy
正确存储模糊参数
计算中使用非模糊bins$breaks
,但据我所知(如果我错了,请纠正我)bins$fuzzy
不是。< / p>
如果我只是将bins$breaks
替换为bins$fuzzy
顶部的bin_vector
,则会返回正确的图表。不是错误的证明,而是建议可能可以采取更多措施来模拟先前版本ggplot2
的行为。
在bin_vector
的顶部,我希望找到一个可以返回bins$breaks
或bins$fuzzy
的条件。我认为现在不见了。
<强>修补剂强>
要"patch"
bin_vector
函数,请从github源复制函数定义,或者更方便地从终端复制函数定义:
ggplot2:::bin_vector
修改它(修补它)并将其分配到命名空间:
library("ggplot2")
bin_vector <- function (x, bins, weight = NULL, pad = FALSE)
{
... STUFF HERE I HAVE DELETED FOR CLARITY ...
## MY PATCH: Replace bins$breaks with bins$fuzzy
bin_idx <- cut(x, bins$fuzzy, right = bins$right_closed,
include.lowest = TRUE)
... STUFF HERE I HAVE DELETED FOR CLARITY ...
ggplot2:::bin_out(bin_count, bin_x, bin_widths)
## THIS IS THE PATCHED FUNCTION
}
assignInNamespace("bin_vector", bin_vector, ns = "ggplot2")
df <- data.frame(var = seq(-100,100,10)/100)
ggplot(data = df, aes(x = var)) + geom_histogram(aes(y = ..count..), binwidth = 0.05, boundary = 1, closed = "left")
为了清楚起见,上面的代码是为了清晰起见而编辑的:该函数有很多类型检查和我已删除的其他计算,但您需要修补该函数。在运行修补程序之前,请重新启动R会话或detach
当前加载的ggplot2
。
OLD VERSIONS
在版本2.0.9.3
或2.1.0.1
中观察到意外行为 NOT ,并且似乎来自当前版本2.2.0.1
(或者可能是较早的{{1}当我试图调用它时,这给了我一个错误)。
要安装和加载旧版本,比如说2.2.0.0
,请创建一个单独的目录(无需覆盖当前版本),比如ggplot2_0.9.3
:
ggplot2093
要加载旧版本,请从本地目录中调用它:
URL <- "http://cran.r-project.org/src/contrib/Archive/ggplot2/ggplot2_0.9.3.tar.gz"
install.packages(URL, repos = NULL, type = "source",
lib = "~/R/testing/ggplot2093")