r - 将ggplot2中的十六进制垃圾箱设置为相同大小

标签 r ggplot2 hexagonal-tiles

我正在尝试在几种类别中用十六进制表示数据。问题是,对这些垃圾箱进行分面似乎会使它们的大小不同。

set.seed(1) #Create data
bindata <- data.frame(x=rnorm(100), y=rnorm(100))
fac_probs <- dnorm(seq(-3, 3, length.out=26))
fac_probs <- fac_probs/sum(fac_probs)
bindata$factor <- sample(letters, 100, replace=TRUE, prob=fac_probs)

library(ggplot2) #Actual plotting
library(hexbin)

ggplot(bindata, aes(x=x, y=y)) +
  geom_hex() +
  facet_wrap(~factor)




是否可以进行设置以使所有这些垃圾箱的大小相同?

最佳答案

正如朱利叶斯所说,问题在于hexGrob无法获取有关bin大小的信息,而是根据其在构面内发现的差异来猜测。
显然,将dxdy设置为hexGrob是有意义的-不具有六边形的宽度和高度就像通过中心指定一个圆而不给出半径。
解决方法:

如果构面包含x和y都不同的两个相邻六边形,则resolution策略有效。因此,作为一种解决方法,我将手动构造一个data.frame,其中包含单元格的x和y中心坐标,以及刻面的因子和计数:
除了问题中指定的库外,我还需要

library (reshape2)

而且bindata$factor实际上需要成为一个因素:
bindata$factor <- as.factor (bindata$factor)

现在,计算基本六边形网格
h <- hexbin (bindata, xbins = 5, IDs = TRUE, 
             xbnds = range (bindata$x), 
             ybnds = range (bindata$y))

接下来,我们需要根据bindata$factor计算计数
counts <- hexTapply (h, bindata$factor, table)
counts <- t (simplify2array (counts))
counts <- melt (counts)
colnames (counts)  <- c ("ID", "factor", "counts")

由于有了单元格ID,我们可以将此data.frame与适当的坐标合并:
hexdf <- data.frame (hcell2xy (h),  ID = h@cell)
hexdf <- merge (counts, hexdf)

这是data.frame的样子:
> head (hexdf)
  ID factor counts          x         y
1  3      e      0 -0.3681728 -1.914359
2  3      s      0 -0.3681728 -1.914359
3  3      y      0 -0.3681728 -1.914359
4  3      r      0 -0.3681728 -1.914359
5  3      p      0 -0.3681728 -1.914359
6  3      o      0 -0.3681728 -1.914359

ggplot ting(使用下面的命令)将产生正确的bin大小,但该图的外观有点怪异:绘制了0个计数的六边形,但仅在填充了此bin的其他其他方面。为了阻止图形,我们可以在那里将计数设置为NA并使na.value完全透明(默认为grey50):
hexdf$counts [hexdf$counts == 0] <- NA

ggplot(hexdf, aes(x=x, y=y, fill = counts)) +
  geom_hex(stat="identity") +
  facet_wrap(~factor) +
  coord_equal () +
  scale_fill_continuous (low = "grey80", high = "#000040", na.value = "#00000000")

在帖子顶部产生该图。
只要binwidths正确无小面,该策略就可以工作。如果二进制宽度设置得很小,则resolution可能仍会产生太大的dxdy。在这种情况下,我们可以为hexGrob提供两个相邻的bin(但x和y有所不同),每个面的NA计数。
dummy <- hgridcent (xbins = 5, 
                    xbnds = range (bindata$x),  
                    ybnds = range (bindata$y),  
                    shape = 1)

dummy <- data.frame (ID = 0,
                     factor = rep (levels (bindata$factor), each = 2),
                     counts = NA,
                     x = rep (dummy$x [1] + c (0, dummy$dx/2), 
                              nlevels (bindata$factor)),
                     y = rep (dummy$y [1] + c (0, dummy$dy  ), 
                              nlevels (bindata$factor)))

这种方法的另一个优点是,我们可以删除counts中已经计数为0的所有行,在这种情况下,将hexdf的大小减少大约3/4(122行而不是520行):
counts <- counts [counts$counts > 0 ,]
hexdf <- data.frame (hcell2xy (h),  ID = h@cell)
hexdf <- merge (counts, hexdf)
hexdf <- rbind (hexdf, dummy)

该图看起来与上面的图完全相同,但是您可以在na.value并不完全透明的情况下看到差异。

有关该问题的更多信息
问题不是刻面独有,但如果占用的存储箱太少,则总是会发生此问题,因此不会填充“对角线”相邻的存储箱。
这是显示问题的一系列更简单的数据:
首先,我追踪hexBin,以便获得与ggplot2:::hexBin相同的六边形网格和hexbin返回的对象的所有中心坐标:
trace (ggplot2:::hexBin, exit = quote ({trace.grid <<- as.data.frame (hgridcent (xbins = xbins, xbnds = xbnds, ybnds = ybnds, shape = ybins/xbins) [1:2]); trace.h <<- hb}))

设置一个非常小的数据集:
df <- data.frame (x = 3 : 1, y = 1 : 3)

并绘制:
p <- ggplot(df, aes(x=x, y=y)) +  geom_hex(binwidth=c(1, 1)) +          
     coord_fixed (xlim = c (0, 4), ylim = c (0,4))

p # needed for the tracing to occur
p + geom_point (data = trace.grid, size = 4) + 
    geom_point (data = df, col = "red") # data pts

str (trace.h)

Formal class 'hexbin' [package "hexbin"] with 16 slots
  ..@ cell  : int [1:3] 3 5 7
  ..@ count : int [1:3] 1 1 1
  ..@ xcm   : num [1:3] 3 2 1
  ..@ ycm   : num [1:3] 1 2 3
  ..@ xbins : num 2
  ..@ shape : num 1
  ..@ xbnds : num [1:2] 1 3
  ..@ ybnds : num [1:2] 1 3
  ..@ dimen : num [1:2] 4 3
  ..@ n     : int 3
  ..@ ncells: int 3
  ..@ call  : language hexbin(x = x, y = y, xbins = xbins, shape = ybins/xbins, xbnds = xbnds, ybnds = ybnds)
  ..@ xlab  : chr "x"
  ..@ ylab  : chr "y"
  ..@ cID   : NULL
  ..@ cAtt  : int(0) 

我重复绘图,忽略了数据点2:
p <- ggplot(df [-2,], aes(x=x, y=y)) +  geom_hex(binwidth=c(1, 1)) +          coord_fixed (xlim = c (0, 4), ylim = c (0,4))
p
p + geom_point (data = trace.grid, size = 4) + geom_point (data = df, col = "red")
str (trace.h)

Formal class 'hexbin' [package "hexbin"] with 16 slots
  ..@ cell  : int [1:2] 3 7
  ..@ count : int [1:2] 1 1
  ..@ xcm   : num [1:2] 3 1
  ..@ ycm   : num [1:2] 1 3
  ..@ xbins : num 2
  ..@ shape : num 1
  ..@ xbnds : num [1:2] 1 3
  ..@ ybnds : num [1:2] 1 3
  ..@ dimen : num [1:2] 4 3
  ..@ n     : int 2
  ..@ ncells: int 2
  ..@ call  : language hexbin(x = x, y = y, xbins = xbins, shape = ybins/xbins, xbnds = xbnds, ybnds = ybnds)
  ..@ xlab  : chr "x"
  ..@ ylab  : chr "y"
  ..@ cID   : NULL
  ..@ cAtt  : int(0) 



请注意,来自hexbin的结果在同一网格上(单元格编号未更改,仅不再填充单元格5,因此未列出),网格尺寸和范围未更改。但是绘制的六边形确实发生了巨大变化。

另请注意,hgridcent忘记返回第一个单元格的中心坐标(左下方)。


尽管已填充:
df <- data.frame (x = 1 : 3, y = 1 : 3)

p <- ggplot(df, aes(x=x, y=y)) +  geom_hex(binwidth=c(0.5, 0.8)) +          
     coord_fixed (xlim = c (0, 4), ylim = c (0,4))

p # needed for the tracing to occur
p + geom_point (data = trace.grid, size = 4) + 
    geom_point (data = df, col = "red") + # data pts
    geom_point (data = as.data.frame (hcell2xy (trace.h)), shape = 1, size = 6)


在此,六边形的渲染可能不正确-它们不属于一个六边形网格。

关于r - 将ggplot2中的十六进制垃圾箱设置为相同大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14495111/

相关文章:

r - 编写 tidyeval 函数以重命名 dplyr 中的因子级别

c - 这是 lapack 问题还是我的代码中的错误?

r - 错误: ScalesList was built with an incompatible version of ggproto

php - 在六边形场上通过螺旋创建单元格的算法

algorithm - 生成 Catan 数字的定居者?

r - fs::dir_ls() 为内部包含中文字符的文件路径返回不可读的输出

r - 分层/多级饼图

使用 coord_polar() 时旋转 x 轴文本

r - 在 ggplot2 中绘制白天(无日期)

java - 是否可以制作多边形边界框?