Как построить серию смешанных частот с NAs в ggplot?

#r #ggplot2

Вопрос:

У меня есть следующие таблицы данных x :

 x1 <- data.frame(Date = seq(as.Date("2010-01-01"), 
                           as.Date("2012-12-01"), 
                           by = "month"), 
                TS1 = rnorm(36,0,1), 
                TS2 = rnorm(36,0,1), 
                stringsAsFactors = F)

x2 <- data.frame(Date = seq(as.Date("2010-01-01"), 
                           as.Date("2012-12-01"), 
                           by = "quarter"), 
                TS3 = rnorm(12,0,1), 
                stringsAsFactors = F)

x <- left_join(x1, x2, by = "Date")

 

x содержит две ежемесячные серии, в то время как одна-ежеквартальная.

Я хотел бы построить сюжет всех трех серий одновременно с ggplot . Я осознаю dualplot , как это можно сделать. Проблема с ним, однако, заключается в том, что он позволяет построить только 2 смешанных частотных ряда.

Есть ли кто-нибудь, кто может мне в этом помочь?

Спасибо!

Ответ №1:

Обратите внимание, что ggplot требуется длинный формат, поэтому мы сначала используем tidyr::pivot_longer .

Далее, мы можем построить график TS1 и TS2 легко, но TS3 не будем строить график вообще, так как он содержит пропущенные значения.

Один из вариантов-построить линию с пропусками с помощью отдельного geom_line вызова:

 x2 <- x %>%
  tidyr::pivot_longer(cols = c(TS1, TS2, TS3), names_to = "TS") %>%
  mutate(TS = as.factor(TS))

ggplot(x2, aes(x = Date, y = value, group = TS, color = TS))   
  geom_line()   
  geom_line(data = subset(x2, TS == "TS3" amp; !is.na(value)))
 

введите описание изображения здесь

Комментарии:

1. отличное решение! Большое спасибо!

Ответ №2:

В этом случае ggplot не требуется, чтобы данные были преобразованы в длинный формат (хотя это хорошее решение, если вы знакомы с преобразованием данных, и рекомендуется, особенно если нужно было построить много столбцов или отдельных строк).

Для простоты, особенно при обучении ggplot , я могу предложить альтернативное решение.

TS1 и TS2 могут быть легко сопоставлены с датой, так как ни у NA того, ни у другого нет значений. Здесь мы вызываем geom_line() дважды, по одному для каждой линии:

 x %>%  
  ggplot() 
  geom_line(aes(Date, TS1), colour = 'red') 
  geom_line(aes(Date, TS2), colour = 'blue')
 

введите описание изображения здесь

Если вы попытаетесь включить третью geom_line() с TS3 , будут нанесены только исходные две строки из TS3 -за пропущенных значений ( NA ). Решение состоит в том, чтобы заполнить NA значения в данных перед построением графика, используя zoo::na.approx() . Как следует из названия, zoo::na.approx() способен приближать значения, когда у вас есть NA s, с помощью линейной интерполяции. В этом случае я предполагаю, что линейная интерполяция между известными значениями подходит для построения графика (как geom_line и в любом случае). Ознакомьтесь с ?zoo::na.approx более подробной информацией, включая нелинейную интерполяцию.

zoo::na.approx(TS3, Date, na.rm = FALSE) может быть прочитано вслух, например: «Мы хотим приблизить значения TS3 , когда они отсутствуют ( NA ), на основе значений Date , и если в интерполированных данных все еще есть NA s, сохраните NA значения, которые мы можем приблизить».

 x %>%
  mutate(
    TS3 = zoo::na.approx(TS3, Date, na.rm = FALSE)
  ) %>% 
  ggplot() 
  geom_line(aes(Date, TS1), colour = 'red') 
  geom_line(aes(Date, TS2), colour = 'blue') 
  geom_line(aes(Date, TS3), colour = 'green')
 

введите описание изображения здесь

Обратите внимание, что зеленая линия заканчивается чуть короче (2 точки данных) двух других строк. Это связано с тем, что по умолчанию zoo::na.approx() не выполняется интерполяция, когда NA она не находится между двумя известными точками данных. Вот почему мы указали na.rm = FALSE при выполнении интерполяции. Посмотрите на страницу справки ?zoo::na.approx для поиска альтернатив (например, повторения последнего известного наблюдения).