geom_histogram:错误的垃圾箱?

2024-03-08

我正在使用 ggplot 2.1.0 来绘制直方图,并且我对直方图箱有意外的行为。 我在这里举了一个左封闭 bin 的示例(即 [ 0, 0.1 [ ),binwidth 为 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[...等] 中。

这里有什么我不完全理解的东西吗(特别是新的“中心”和“边界”参数)?或者 ggplot2 在那里做了奇怪的事情?

提前致谢, 此致, 阿尔诺

PS:这里还问:https://github.com/hadley/ggplot2/issues/1651 https://github.com/hadley/ggplot2/issues/1651


Edit:下面描述的问题已在最近的版本中修复ggplot2.

正如罗兰的评论中所建议的,您的问题是可重现的,并且似乎是由舍入错误引起的。在这一点上,这在我看来像是版本中引入的错误ggplot2_2.0.0。我在下面推测其起源,但首先让我提出一个基于以下内容的解决方法boundary选项。

PROBLEM:

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

SOLUTION

调整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(更高版本)。

CAUSE:

问题明显地出现在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

舍入误差?

好像:

    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 and stat-bin.r in 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 ...
}

通过将这些函数的当前版本与旧版本进行比较,您应该能够找到不同行为的原因...待续...

调试总结

By "patching" the bin_vector函数并将输出打印到屏幕上,看起来:

  1. bins$fuzzy正确存储模糊参数

  2. 非模糊bins$breaks用于计算,但据我所知(如果我错了请纠正我)bins$fuzzy不是。

  3. 如果我简单地替换bins$breaks with bins$fuzzy在顶端bin_vector,返回正确的图。不是错误的证明,而是建议也许可以做更多的事情来模拟以前版本的行为ggplot2.

  4. 在顶端bin_vector我希望找到一个返回的条件bins$breaks or bins$fuzzy。我想现在已经不见了。

PATCHING

To "patch" the 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.

旧版本

意想不到的行为是NOT在版本中观察到2.0.9.3 or 2.1.0.1并且似乎源自当前版本2.2.0.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") 

要加载旧版本,请从本地目录调用它:

library("ggplot2", lib.loc = "~/R/testing/ggplot2093") 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

geom_histogram:错误的垃圾箱? 的相关文章

  • 如何使用 R 计算成为列表中中位数的概率?

    假设我有以下数据集 其中显示了假设实验的每个状态的三个观察结果的列表 state lt c Iowa Minnesota Illinois outcome lt list c 5 11 11 c 3 12 8 c 9 14 2 dat lt
  • 通过间接引用列来修改数据框中的某些值

    我正在整理一些数据 我们将失败的数据分类到垃圾箱中 并按批次计算每个分类箱的有限产量 我有一个描述排序箱的元表 这些行按升序测试顺序排列 一些排序标签带有非语法名称 sort tbl lt tibble tribble weight lab
  • 如何使用 usmap 标记数字而不是名称?

    我知道 usmap 有一个选项label in plot usmap 我想标记一些数字 而不是状态名称 我想 usmap 中应该有与州质心坐标相关的数据 但我不知道如何找到它 如果我能得到 坐标然后我可以用它来标记数字geom text 这
  • 绘制点之间的所有线

    我有以下 R 代码 x lt c 0 01848598 0 08052353 0 06741172 0 11652034 y lt c 0 4177541 0 4042247 0 3964025 0 4074685 d lt data fr
  • 尝试读取 CSV 文件时出现“无法识别的字符串转义”

    我正在尝试导入一个 csv文件 以便我可以观看此视频 R ggplot2 图形直方图 http www youtube com watch v 47kWynt3b6M 我安装了所有正确的软件包 包括ggplot以及相关的包 视频中的第一个说
  • 从命令行运行 R 代码 (Windows)

    我在名为 analysis r 的文件中有一些 R 代码 我希望能够从命令行 CMD 运行该文件中的代码 而无需通过 R 终端 并且我还希望能够传递参数并在我的代码中使用这些参数 例如就像下面的伪代码 C gt execute r scri
  • 为什么 dplyr filter() 不能在函数内工作(即使用变量作为列名)?

    使用 dplyr 函数对数据进行过滤 分组和变异的函数 基本管道序列在函数之外工作得很好 这就是我使用真实列名称的地方 将其放入一个函数中 其中列名称是一个变量 并且某些函数可以工作 但有些函数则不能 尤其是 dplyr filter 例如
  • 在 R 中使用 lapply 绘制多个数据帧

    我正在尝试使用 lapply 函数绘制多个数据帧 每个数据帧一个图 但是尽管有关此主题的所有帖子我都找不到答案 因为我不断收到错误 图的输出列表为空 我的数据结构如下 df1 lt mtcars gt group by cyl gt tal
  • 基于时间窗口的不规则时间序列的优化滚动函数

    有没有办法使用 rollapply 来自zoo包或类似的东西 优化功能 rollmean rollmedian等 使用基于时间的窗口计算滚动函数 而不是基于大量观察的函数 我想要的很简单 对于不规则时间序列中的每个元素 我想计算一个具有 N
  • 如何在 R 或 Python 中制作旭日图?

    到目前为止 我一直无法找到一个可以创建旭日图的 R 库约翰 斯塔斯科 http www cc gatech edu gvu ii sunburst 有人知道如何在 R 或 Python 中实现这一点吗 在极坐标投影中使用 matplotli
  • 为什么 R 更新后 sim_slopes() 中会出现此错误?

    我正在尝试使用 交互 包来创建简单斜率的约翰逊 尼曼图 但是 当尝试运行 sim slopes 函数时 出现以下错误 直到我将R更新到4 2 2 我才没有遇到这个问题 我使用的是 macOS Ventura 13 1 Error class
  • 如何从 R 中的 txt 文件读取矩阵?

    我有一个带有矩阵的txt文件 Matrix txt 重要 数字之间没有空格 0100 1001 1100 我想在 R 中将其作为矩阵读取 我该怎么做 我尝试使用 as matrix read table Matrix txt sep 但失败
  • read_html(url) 和 read_html(content(GET(url), "text")) 之间的区别

    我正在看这个很棒的答案 https stackoverflow com a 58211397 3502164 https stackoverflow com a 58211397 3502164 解决方案的开头包括 library httr
  • 以编程方式将字符串宽度值插入到 sprintf() 中

    我正在尝试以编程方式将字符串宽度值插入到sprintf 格式 期望的结果是 sprintf 20s hello 1 hello 但我想插入20在同一通话中即时进行 因此它可以是任何号码 我努力了 sprintf ds 20 hello 1
  • 删除极坐标图边缘的多余空间和圆环

    我有一个极坐标图ggplot2我已经非常接近完成 相当简单的情节 我已经能够在删除矩形边框方面获得帮助 但我不需要删除最后一个范围轮廓与带有方位角标签的绘图周围的环之间的额外空间 我希望该图的边界为 15 000 而不是 15 214 我编
  • SPSS 中的标准化残差与 R rstandard(lm()) 不匹配

    在寻找 R 相关解决方案时 我发现 R 和 SPSS 版本 24 在计算简单线性模型中的标准化残差方面存在一些不一致 看来SPSS所谓的标准化残差匹配 R学生化残差 我完全不认为某处存在软件错误 但显然这两个程序之间存在差异 看看这个例子
  • applyStrategy 错误

    我是R新手 最近运行后遇到以下错误applyStrategy函数来自quantstrat包裹 Error in eval expr envir enclos object signal not found Error in colnames
  • 使用 template.docx 从 Shiny App 编织 Word 文档

    我正在尝试使用 template docx 文件从闪亮的应用程序编写一个 Word 文档 我收到以下错误消息 pandoc exe template docx openBinaryFile 不存在 没有这样的文件或目录 以下 3 个文件当前
  • 如何修复 R 中 Kaplan Meier 图的风险表计算错误

    以下是一个数据帧 其中 6 个参与者中的每一个都有唯一的 record ID 我想绘制一个生存分析图 其中包含感兴趣事件的复发以及在时间间隔 tstart 到 tstop 内 暴露 药物剂量 数值变量 的时间依赖性协变量 每个参与者的最大
  • 在 ifelse() 语句内部和外部运行一行时的不同输出

    我正在尝试运行一个简单的命令 但不知道为什么在内部和外部运行它时输出不同ifelse 功能 函数条件评估为FALSE 所以输出应该完全相同 但是 单独运行时 输出为0 0 1 1 0 1 0 1 NA 根据需要 但是从ifelse 函数 输

随机推荐