ggplot2 geom_bar 定位失败

ggplot2 geom_bar position failure

我在 geom_bar 中使用 ..count.. 转换并收到警告 position_stack 需要非重叠 x 间隔 当我的某些类别计数很少时。

这最好使用一些模拟数据来解释(我的数据涉及方向和风速,我保留了与之相关的名称)

#make data
set.seed(12345)
FF=rweibull(100,1.7,1)*20  #mock speeds
FF[FF>60]=59
dir=sample.int(10,size=100,replace=TRUE) # mock directions

#group into speed classes
FFcut=cut(FF,breaks=seq(0,60,by=20),ordered_result=TRUE,right=FALSE,drop=FALSE)

# stuff into data frame & plot
df=data.frame(dir=dir,grp=FFcut)
ggplot(data=df,aes(x=dir,y=(..count..)/sum(..count..),fill=grp)) + geom_bar()

这很好用,结果图显示了根据速度分组的方向频率。相关的是,计数最少的速度 class(此处为“[40,60]”)将有 5 个计数。

然而,更高的速度 classes 会导致警告。例如,

FFcut=cut(FF,breaks=seq(0,60,by=15),ordered_result=TRUE,right=FALSE,drop=FALSE)
 

计数最少的速度 class(现在是“[45,60]”)将只有 3 个计数,ggplot2 会警告

position_stack 要求 x 间隔不重叠

并且该图将显示该类别中的数据沿 x 轴展开。 似乎 5 是一个组要使其正常工作所需的最小大小。

我很想知道这是 stat_bingeom_bar 正在使用)中的功能还是错误,或者我是否只是在滥用 geom_bar

此外,如有任何解决此问题的建议,我们将不胜感激。

此致

这并没有直接解决问题,因为我也不知道重叠值是怎么回事,但这是一个由 dplyr 提供支持的解决方法,而且最终可能会更加灵活.

无需依靠 geom_bar 来获取切割因子并通过 ..count../sum(..count..) 为您提供份额,您可以轻松地自己预先计算这些份额,然后绘制您的条形图。我个人喜欢对我的数据以及我正在绘制的内容进行这种类型的控制。

首先,我将dirFF放入一个数据框/tbl_df,然后切割FF。然后 count 让我按 dirgrp 对数据进行分组并计算这两个变量的每个组合的观察次数,然后计算每个 n 的份额n 的总和。我正在使用 geom_col,它类似于 geom_bar,但是当您在 aes.

中有一个 y 值时
library(tidyverse)

set.seed(12345)
FF <- rweibull(100,1.7,1) * 20  #mock speeds
FF[FF > 60] <- 59
dir <- sample.int(10, size = 100, replace = TRUE) # mock directions

shares <- tibble(dir = dir, FF = FF) %>%
  mutate(grp = cut(FF, breaks = seq(0, 60, by = 15), ordered_result = T, right = F, drop = F)) %>%
  count(dir, grp) %>%
  mutate(share = n / sum(n))

shares
#> # A tibble: 29 x 4
#>      dir grp         n share
#>    <int> <ord>   <int> <dbl>
#>  1     1 [0,15)      3  0.03
#>  2     1 [15,30)     2  0.02
#>  3     2 [0,15)      4  0.04
#>  4     2 [15,30)     3  0.03
#>  5     2 [30,45)     1  0.01
#>  6     2 [45,60)     1  0.01
#>  7     3 [0,15)      6  0.06
#>  8     3 [15,30)     1  0.01
#>  9     3 [30,45)     2  0.02
#> 10     4 [0,15)      6  0.06
#> # ... with 19 more rows

ggplot(shares, aes(x = dir, y = share, fill = grp)) +
  geom_col()

发生这种情况是因为 df$dir 是数字,所以 ggplot 对象假定一个连续的 x 轴,美学参数 group 基于唯一已知的离散变量 (fill = grp) .

因此,当 grp = [45,60) 中根本没有那么多 dir 值时,ggplot 会对每个条形应该有多宽感到困惑。如果我们将情节分成不同的方面,这在视觉上会变得更加明显:

ggplot(data=df,
            aes(x=dir,y=(..count..)/sum(..count..),
                fill = grp)) + 
  geom_bar() + 
  facet_wrap(~ grp)

> for(l in levels(df$grp)) print(sort(unique(df$dir[df$grp == l])))
[1]  1  2  3  4  6  7  8  9 10
[1]  1  2  3  4  5  6  7  8  9 10
[1]  2  3  4  5  7  9 10
[1] 2 4 7

我们还可以手动检查排序后的 df$dir 值之间的最小差异对于前三个 grp 值是 1,但对于最后一个值是 2。因此默认条形宽度更宽。

以下解决方案应该都能达到相同的结果:

1.为 geom_bar():

中的所有组明确指定相同的条宽
ggplot(data=df,
       aes(x=dir,y=(..count..)/sum(..count..),
           fill = grp)) + 
  geom_bar(width = 0.9)

2。在将 dir 传递给 aes(x = ...):

之前将其转换为分类变量
ggplot(data=df,
       aes(x=factor(dir), y=(..count..)/sum(..count..),
           fill = grp)) + 
  geom_bar()

3。指定 group 参数应同时基于 df$dir & df$grp:

ggplot(data=df,
       aes(x=dir,
           y=(..count..)/sum(..count..),
           group = interaction(dir, grp),
           fill = grp)) + 
  geom_bar()