【问题标题】:ggplot2 geom_bar position failureggplot2 geom_bar 位置失败
【发布时间】:2018-11-09 06:31:28
【问题描述】:

我在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()

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

但是,更多的速度等级会导致警告。例如,与

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

计数最少的速度类(现在“[45,60)”)只有 3 个计数,ggplot2 会发出警告

position_stack 需要不重叠的 x 间隔

并且该图将显示此类别中沿 x 轴分布的数据。 似乎 5 是组正常工作的最小规模。

如果我知道这是 stat_bingeom_bar 正在使用)中的功能还是错误,或者我只是在滥用 geom_bar,我将不胜感激。

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

真诚的

【问题讨论】:

  • 也许是这个? ggplot(data=df,aes(dir, fill=grp)) + geom_histogram(aes(y=(..count..)/sum(..count..)))

标签: r ggplot2 histogram stacked


【解决方案1】:

出现这种情况是因为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$dirdf$grp

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

【讨论】:

  • 非常感谢。顺便说一句,我的原始代码将 dir 作为分类变量,但我正在处理的情节要复杂得多,并且还添加了 `coord_polar()`。对于圆形图,当我将其他图层添加到图中时,x 轴的离散性会导致麻烦。有一个连续的 x 轴解决了这些问题,但也许这个解决方案还为时过早.....
  • 旁注:我在尝试将标签传递给 plotly 时出现了这个问题。虽然通过指定宽度来固定 ggplot(上面的解决方案#1),但传递给 plotly 的标签变为 NA。解决方案 #3 效果很好。
【解决方案2】:

这并不能直接解决问题,因为我也不知道重叠值发生了什么,但这是dplyr 提供动力的解决方法,并且可能会变得更加灵活。

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

首先,我将dirFF放入一个数据框/tbl_df,并剪切FF。然后count 让我将数据按dirgrp 分组,并计算这两个变量的每个组合的观察次数,然后计算每个nn 总和中的份额。我正在使用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()

【讨论】:

  • 谢谢卡米尔。这非常有用。我一直在考虑使代码更加明确。问题是我正在更新我在 2001 年在 base R 中编写的绘图例程(从那时起一直在使用),然后一切都被明确计算。很麻烦,但我知道我有什么。您的解决方案非常优雅,而且一点也不麻烦......
猜你喜欢
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多