Ошибка позиции ggplot2 geom_bar - PullRequest
0 голосов
/ 30 мая 2018

Я использую преобразование ..count.. в geom_bar и получаю предупреждение 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 отсчетов.Three categories of size 20 each

Однако большее количество классов скорости приводит к предупреждению.Например, при

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

класс скорости с наименьшим количеством импульсов (теперь «[45,60)») будет иметь только 3 счета, а ggplot2 предупредит, что

position_stackтребует неперекрывающихся интервалов x

, и на графике будут отображаться данные в этой категории, распределенные вдоль оси x.Four categories of size 15 each. Now the last one with three elements is not added on top of the corresponding bar Кажется, что 5 - это минимальный размер для группы, чтобы он мог работать правильно.

Я был бы признателен, если бы знал, является ли это функцией или ошибкой в ​​stat_bin(который geom_bar использует) или если я просто злоупотребляю geom_bar.

Также, любые предложения, как обойти это, будут оценены.

С уважением

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Это происходит потому, что df$dir является числовым, поэтому объект ggplot предполагает непрерывную ось x, а эстетический параметр group основан на единственной известной дискретной переменной (fill = grp).

AsВ результате, когда в grp = [45,60) значений dir просто не так много, ggplot не понимает, какой ширины должен быть каждый столбец.Это становится более наглядным, если мы разделим график на разные грани:

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

facet view

> 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 значениями является 1 для первых трех grp значений, но 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()

plot

0 голосов
/ 30 мая 2018

Это напрямую не решает проблему, потому что я также не понимаю, что происходит с перекрывающимися значениями, но это обходной путь с поддержкой dplyr и может в любом случае оказаться более гибким.

Вместо того, чтобы полагаться на geom_bar, чтобы взять коэффициент сокращения и дать вам доли через ..count../sum(..count..), вы можете достаточно легко просто рассчитать эти доли самостоятельно, а затем построить свои бары.Мне лично нравится этот тип контроля над моими данными и именно тем, что я планирую.

Сначала я помещаю dir и FF во фрейм данных / tbl_df и вырезаю FF.Затем count позволяет мне сгруппировать данные по dir и grp и подсчитать количество наблюдений для каждой комбинации этих двух переменных, а затем вычислить долю каждого n над суммой n.Я использую geom_col, что похоже на geom_bar, но когда у вас есть y значение в вашем aes.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...