GGPlot объединяет / накладывает столбчатые и линейные диаграммы (диаграммы Ганта) - PullRequest
2 голосов
/ 21 января 2020

Я хотел бы наложить данные об осадках (столбец) на диаграмму Ганта, которая содержит «предлагаемые посевы windows» и фактические даты посева. Из набора данных я могу создать оба отдельно, но не на одном графике. Любые указатели очень ценятся.

enter image description here

## plot Gantt chart with suggested sowing dates and actual sowing dates
sowdate.df$Element <- factor(sowdate.df$Element,levels=c("SOWING DATE","Dart","Spitfire","Suntop","Beckom","Flanker","Lancer","Sunmax","Kittyhawk"))
ggplot(sowdate.df, aes(Date1, Element, Color=Category, group=Item)) +
  geom_line(size = 10) 

## plot rainfall
ggplot(sowdate.df, aes(Date1, rain)) + geom_col()


## combine Gantt and rainfall
ggplot(sowdate.df) + 
  geom_col(aes(Date1, rain), size = 1, color = "darkblue", fill = "white") +
  geom_line(aes(Date1, Element, Color=Category, group=Item), size = 1.5, color="red", group = 1)



      Item     Element    Category Start-End      Date1 rain
1     1      Beckom     Variety     Start 2018-05-07   NA
2     2        Dart     Variety     Start 2018-06-01   NA
3     3     Flanker     Variety     Start 2018-05-01   NA
4     4   Kittyhawk     Variety     Start 2018-04-01   NA
5     5      Lancer     Variety     Start 2018-05-01   NA
6     6 SOWING DATE Sowing date     Start 2018-06-06   NA
7     7 SOWING DATE Sowing date     Start 2018-06-26   NA
8     8 SOWING DATE Sowing date     Start 2018-07-03   NA
9     9 SOWING DATE Sowing date     Start 2018-07-12   NA
10   10    Spitfire     Variety     Start 2018-05-21   NA
11   11      Sunmax     Variety     Start 2018-04-15   NA
12   12      Suntop     Variety     Start 2018-05-07   NA
13    1      Beckom     Variety       End 2018-05-31   NA
14    2        Dart     Variety       End 2018-06-30   NA
15    3     Flanker     Variety       End 2018-05-21   NA
16    4   Kittyhawk     Variety       End 2018-05-07   NA
17    5      Lancer     Variety       End 2018-05-21   NA
18    6 SOWING DATE Sowing date       End 2018-06-07   NA
19    7 SOWING DATE Sowing date       End 2018-06-27   NA
20    8 SOWING DATE Sowing date       End 2018-07-04   NA
21    9 SOWING DATE Sowing date       End 2018-07-13   NA
22   10    Spitfire     Variety       End 2018-06-21   NA
23   11      Sunmax     Variety       End 2018-05-07   NA
24   12      Suntop     Variety       End 2018-06-07   NA
25   13        <NA>    Rainfall      <NA> 2018-04-14  3.0
26   14        <NA>    Rainfall      <NA> 2018-03-30  7.0
27   15        <NA>    Rainfall      <NA> 2018-06-10  3.5
28   16        <NA>    Rainfall      <NA> 2018-06-18  4.0
29   17        <NA>    Rainfall      <NA> 2018-06-28 13.5
30   18        <NA>    Rainfall      <NA> 2018-07-23  3.0
31   19        <NA>    Rainfall      <NA> 2018-08-05  6.0
32   20        <NA>    Rainfall      <NA> 2018-08-25 23.0
33   21        <NA>    Rainfall      <NA> 2018-09-10  5.0

1 Ответ

2 голосов
/ 22 января 2020

Как вы можете видеть на изображении, которое вы разместили - график, который вам показан, просто перекрывает два графика. Хотя это также возможно сделать с ggplot2, я не нахожу это очень элегантным и может быть очень сложным, потому что вам нужно найти точное положение обоих графиков, чтобы оно выглядело аккуратно.

Ваш обходной путь, использующий geom_line с вашими уровнями факторов в качестве значений y, интересен, но я не уверен, если это так желательно.

В любом случае - это, вероятно, суть вашей проблемы. Вы смешиваете разные меры y - а они принадлежат к разным классам . Уровни коэффициента для одного графика, цифра c / целое число для другого. Это проблематично c. Я не стал бы стараться и заставить их работать по одной оси y, но я бы скорее создал два графика и объединил их с одним из пакетов, объединяющих графики, например patchwork. Примерно так:

Я переименовал ваши столбцы, я использую пакет от GitHub user @ alisdaire47 для чтения ваших данных, а также изменяю некоторые столбцы для достижения сюжета. Ключ использует правильные классы: даты как даты, цифры как цифры.

Сначала прочитайте ваши данные:

sowdate.df <- read.so::read_so('Item     Element    Category Start_End      Date1 rain
1     1      Beckom     Variety     Start 2018-05-07   NA
2     2        Dart     Variety     Start 2018-06-01   NA
3     3     Flanker     Variety     Start 2018-05-01   NA
4     4   Kittyhawk     Variety     Start 2018-04-01   NA
5     5      Lancer     Variety     Start 2018-05-01   NA
6     6 SOWING DATE Sowing date     Start 2018-06-06   NA
7     7 SOWING DATE Sowing date     Start 2018-06-26   NA
8     8 SOWING DATE Sowing date     Start 2018-07-03   NA
9     9 SOWING DATE Sowing date     Start 2018-07-12   NA
10   10    Spitfire     Variety     Start 2018-05-21   NA
11   11      Sunmax     Variety     Start 2018-04-15   NA
12   12      Suntop     Variety     Start 2018-05-07   NA
13    1      Beckom     Variety       End 2018-05-31   NA
14    2        Dart     Variety       End 2018-06-30   NA
15    3     Flanker     Variety       End 2018-05-21   NA
16    4   Kittyhawk     Variety       End 2018-05-07   NA
17    5      Lancer     Variety       End 2018-05-21   NA
18    6 SOWING DATE Sowing date       End 2018-06-07   NA
19    7 SOWING DATE Sowing date       End 2018-06-27   NA
20    8 SOWING DATE Sowing date       End 2018-07-04   NA
21    9 SOWING DATE Sowing date       End 2018-07-13   NA
22   10    Spitfire     Variety       End 2018-06-21   NA
23   11      Sunmax     Variety       End 2018-05-07   NA
24   12      Suntop     Variety       End 2018-06-07   NA
25   13        <NA>    Rainfall      <NA> 2018-04-14  3.0
26   14        <NA>    Rainfall      <NA> 2018-03-30  7.0
27   15        <NA>    Rainfall      <NA> 2018-06-10  3.5
28   16        <NA>    Rainfall      <NA> 2018-06-18  4.0
29   17        <NA>    Rainfall      <NA> 2018-06-28 13.5
30   18        <NA>    Rainfall      <NA> 2018-07-23  3.0
31   19        <NA>    Rainfall      <NA> 2018-08-05  6.0
32   20        <NA>    Rainfall      <NA> 2018-08-25 23.0
33   21        <NA>    Rainfall      <NA> 2018-09-10  5.0')
#> Warning: 8 parsing failures.
#> row col  expected    actual         file
#>   6  -- 6 columns 8 columns literal data
#>   7  -- 6 columns 8 columns literal data
#>   8  -- 6 columns 8 columns literal data
#>   9  -- 6 columns 8 columns literal data
#>  18  -- 6 columns 8 columns literal data
#> ... ... ......... ......... ............
#> See problems(...) for more details.

Теперь участки

library(tidyverse)
library(patchwork)

Подготовьте данные (беспорядок происходит из-за масштабирования значений до ваших уровней факторов)

sowdate <- sowdate.df %>% mutate(element_f = factor(Element,levels=c("SOWING DATE","Dart","Spitfire","Suntop","Beckom","Flanker","Lancer","Sunmax","Kittyhawk")),
                                 date = as.Date(Date1),
                                 rain = as.numeric(rain),
                                 rain_scaled = rain*max(length(levels(element_f))/max(rain, na.rm = TRUE)))
#> Warning: NAs introduced by coercion

Метод 1 - объединить графики, используя пэчворк. Я рекомендую это, чтобы не смешивать разные классы в один y.

p1 <- ggplot(sowdate, aes(date, element_f, Color = Category, group = Item)) +
  geom_line(size = 10) +
  theme(axis.title.x = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        plot.margin = margin(b = 0))
p2 <- ggplot(sowdate) +
  geom_col(aes(date, rain)) +
  theme(plot.margin = margin(t = 0))
p1 + p2 + plot_layout(nrow = 2, )
#> Warning: Removed 8 rows containing missing values (geom_path).
#> Warning: Removed 24 rows containing missing values (position_stack).

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

Метод 2 Объединение различных классов переменных (я не рекомендую. Это становится довольно грязным , как вы можете видеть выше и ниже ). Вам нужно будет масштабировать значения дождя до уровней факторов, чтобы столбцы перекрывались и не становились слишком длинными. Теперь для этого требуется вторая ось Y. Для этого вы должны сделать ваши уровни факторов нумерацией c, затем создать разрывы и метки для левой оси Y, а затем повторно преобразовать значения дождя в их реальные значения, и надеяться, что этот тип разрывов сработает. Я не думаю, что вторая ось Y действительно помогает читать график.


max_rain <- max(sowdate$rain,na.rm = TRUE)
breaks_ax <- 1:length(levels(sowdate$element_f)) - sum(is.na(levels(sowdate$element_f)))
labels_ax <- as.character(levels(sowdate$element_f)[which(!is.na(levels(sowdate$element_f)))])

ggplot(sowdate, aes(date, as.numeric(element_f), Color = Category, group=Item)) +
  geom_line(size = 10) +
  geom_col(aes(date, rain_scaled)) +
  scale_y_continuous(breaks = breaks_ax, labels = labels_ax, 
                     sec.axis = sec_axis(~ .*max_rain/ max(length(levels(sowdate$element_f))))) +
  labs(y = 'Element')
#> Warning: Removed 24 rows containing missing values (position_stack).
#> Warning: Removed 17 rows containing missing values (geom_path).

Создано в 2020-01-22 пакетом представитель (v0.3.0)

...