Как изобразить разницу между двумя временными рядами с гистограммой на одном графике? - PullRequest
0 голосов
/ 29 августа 2018

Например, если у нас есть два временных ряда a и b:

time <- seq(as.Date("1999-06-15"),as.Date("2008-06-15") , by= "years")
a <- c(22.3,24.1,35,35,35.9,39.2,34.8,31.5,29.1,25.8)    
b <- c(22,24.9,31,34,37.5,36.3,32.1,29.7,28.6,23.9)
plot(as.Date(time),a,type="l",xlab="Date",ylab="T(°C)")
lines(as.Date(time),b,col=2)

Есть ли способ, которым мой график будет выглядеть как пример изображения:

enter image description here

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

К сожалению, первый ответ по метке (до редактирования) содержал серьезный недостаток, из-за которого столбцы, показывающие остатки , были в два раза выше ожидаемых . Это станет сразу видно, когда заполнение столбцов будет окрашено в соответствии с key:

library(dplyr)
library(tidyr)
library(ggplot2)

data_frame(time, a, b) %>%
  mutate(diff_a_b = a - b) %>% 
  gather(key, value, a, b) %>% 
  ggplot(., aes(time)) +
  geom_line(aes(y = value, color = key)) + 
  geom_col(aes(y = diff_a_b, fill = key))

enter image description here

Основная причина в том, что diff_a_b не обрабатывается как переменная при изменении формы с широкого на длинный формат:

data_frame(time, a, b) %>%
  mutate(diff_a_b = a - b) %>% 
  gather(key, value, a, b)

Итак, diff_a_b появляется дважды для каждого time значения:

# A tibble: 20 x 4
   time       diff_a_b key   value
   <date>        <dbl> <chr> <dbl>
 1 1999-06-15    0.3   a      22.3
 2 2000-06-15   -0.800 a      24.1
 3 2001-06-15    4     a      35  
 4 2002-06-15    1     a      35  
 5 2003-06-15   -1.6   a      35.9
 6 2004-06-15    2.9   a      39.2
 7 2005-06-15    2.70  a      34.8
 8 2006-06-15    1.8   a      31.5
 9 2007-06-15    0.5   a      29.1
10 2008-06-15    1.9   a      25.8
11 1999-06-15    0.3   b      22  
12 2000-06-15   -0.800 b      24.9
13 2001-06-15    4     b      31  
14 2002-06-15    1     b      34  
15 2003-06-15   -1.6   b      37.5
16 2004-06-15    2.9   b      36.3
17 2005-06-15    2.70  b      32.1
18 2006-06-15    1.8   b      29.7
19 2007-06-15    0.5   b      28.6
20 2008-06-15    1.9   b      23.9

В качестве значения по умолчанию для geom_col() установлено значение position = "stack", два значения накладываются друг на друга.

Быстрые исправления для ответа Маркуса

Если позиция меняется на "dodge", тогда ответ Маркуса покажет ожидаемый результат

data_frame(time, a, b) %>%
  mutate(diff_a_b = a - b) %>% 
  gather(key, value, a, b) %>% 
  ggplot(., aes(time)) +
  geom_line(aes(y = value, color = key)) + 
  geom_col(aes(y = diff_a_b), position = "dodge")

enter image description here

Другим исправлением будет использование geom_linerange(), где каждый сегмент будет нанесен дважды:

data_frame(time, a, b) %>%
  mutate(diff_a_b = a - b) %>% 
  gather(key, value, a, b) %>% 
  ggplot(., aes(time)) +
  geom_line(aes(y = value, color = key)) + 
  geom_linerange(aes(ymin = 0, ymax = diff_a_b), size = 3)

enter image description here

"Tidy" подход

ИМХО, правильный ("аккуратный") подход - обрабатывать diff_a_b как третью переменную / временной ряд при изменении формы и использовать параметр data при создании geoms:

data_frame(time, a, b) %>%
  mutate(diff_a_b = a - b) %>% 
  gather(, , -time) %>%
  ggplot(aes(x = time, y = value)) +
  geom_line(aes(col = key), data = function(x) filter(x, key != "diff_a_b")) + 
  geom_col(data = function(x) filter(x, key == "diff_a_b"))

enter image description here

data.table и ggplot2

Для тех, кто предпочитает data.table для сбора данных:

library(data.table)
library(ggplot2)
long <- data.table(time, a, b)[
  , diff_a_b := a - b][
    , melt(.SD, "time")]
ggplot() + aes(time, value) + 
  geom_line(aes(color = variable), data = long[variable != "diff_a_b"]) + 
  geom_col(data = long[variable == "diff_a_b"])
0 голосов
/ 29 августа 2018

Вы можете использовать ggplot2 geom_line и geom_col.

library(tidyverse)
DF_bar <- mutate(DF, diff_a_b = a - b)

DF %>% 
  gather(key, value, a, b) %>% 
  ggplot(., aes(time)) +
  geom_line(aes(y = value, col = key)) + 
  geom_col(data = DF_bar, aes(y = diff_a_b)) # or geom_bar(data = DF_bar, aes(y = diff_a_b), stat = "identity")

На первом шаге я создал новый набор данных, который содержит переменную diff_a_b, которая, в общем-то, представляет собой разницу между a и b.

Затем я изменил ваши данные с широкого на длинный, чтобы мы могли сопоставить столбец key с эстетикой цвета в geom_line. Наконец, я использую DF_bar в geom_col для построения diff_a_b.

Данные

DF <- data.frame(time = seq(as.Date("1999-06-15"),as.Date("2008-06-15"), by= "years"),
                 a = c(22.3,24.1,35,35,35.9,39.2,34.8,31.5,29.1,25.8),
                 b = c(22,24.9,31,34,37.5,36.3,32.1,29.7,28.6,23.9))

enter image description here

...