Присвоение линии второй оси y в ggplot

#r #ggplot2

#r #ggplot2

Вопрос:

Я пытаюсь создать довольно сложный график. Результатом должен быть сложенный и сгруппированный столбчатый график с дополнительными линиями на основе второй оси y. До сих пор мне удавалось создать сложенный и сгруппированный столбчатый график (псевдогруппированный, для меня достаточно), но я страдаю при присвоении линейной части второй оси y.

 library(tidyverse)
library(magrittr)

df <- data.frame(
  DATE = c("2019-01-01", "2019-01-08", "2019-01-15")
  , XXX_TY_T = c(20, 30, 25)
  , XXX_TY_C = c(10, 5, 15)
  , XXX_PY_T = c(15, 20, 20)
  , XXX_PY_C = c(20, 20, 15)
  , YYYY_TY_TD = c(0.7, 0.8, 0.75)
  , YYYY_PY_TD = c(0.4, 0.7, 0.6)
)

df_long <- df %>%
  gather(CATEGORY, VALUE, XXX_TY_T:YYYY_PY_TD) %>%
  mutate(CATEGORY2 = c(rep("XXX_TY", 6), rep("XXX_PY", 6), rep(NA, 6))
         , XAXIS = paste0(DATE, " | ", CATEGORY2))

df_long_bar <- df_long %>% filter(!(CATEGORY %in% c("YYYY_TY_TD", "YYYY_PY_TD")))
df_long_line <- df_long %>% filter(CATEGORY %in% c("YYYY_TY_TD", "YYYY_PY_TD")) %>%
  rename(LINE = VALUE) %>%
  mutate(CATEGORY2 = ifelse(CATEGORY == "YYYY_TY_TD", "XXX_TY", "XXX_PY")
         , XAXIS = paste0(DATE, " | ", CATEGORY2)) %>%
  filter(CATEGORY2 == "XXX_PY") %>%
  select(XAXIS, LINE)

df_long_plot <- left_join(df_long_bar, df_long_line, by = c("XAXIS")) 

ggplot(df_long_plot)  
  geom_bar(aes(x = XAXIS, y = VALUE, fill = CATEGORY), stat = "identity", position = "stack")  
  geom_line(aes(x = XAXIS, y = LINE), stat = "identity")   
  scale_y_continuous(sec.axis = sec_axis(~./40))
  

Результат должен выглядеть следующим образом (нарисованная линия не основана на данных, просто для уточнения):

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

Как я могу ввести эту линию в график?

Ответ №1:

Вы можете попробовать следующее с вашим окончательным фреймом данных:

  1. Исключить NA значения из данных, переданных в geom_line ;
  2. Добавьте группирующую переменную к geom_line эстетическим отображениям;
  3. Преобразуйте значение y (используйте преобразование, противоположное тому, которое используется в sec_axis ).
 ggplot(df_long_plot, aes(x = XAXIS))           # put common aes mappings on top
  geom_col(aes(y = VALUE, fill = CATEGORY))    # geom_col() is equivalent to 
                                               # geom_bar(stat = "identity")
  geom_line(data = . %>% na.omit(),
            aes(y = LINE * 40, group = 1))   
  scale_y_continuous(sec.axis = sec_axis(~./40))
  

Я удалил из кода параметры position = "stack" / stat = "identity" , поскольку в любом случае это значения по умолчанию для соответствующих функций geom.

график

Ответ №2:

Проблема в том, что ваш barplot работает с категориями, в то время как ваш линейный график должен работать с числовыми значениями. Таким образом, вы должны соответствующим образом перенести свои значения x.

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

 ggplot()  
   geom_bar(data     = df_long_bar,
            aes(x    = XAXIS, 
                y    = VALUE, 
                fill = CATEGORY), 
            stat     = "identity", 
            position = "stack") 
   geom_line(data    = df_long_line, 
              aes(x  = as.numeric(factor(XAXIS,
                                        levels(as.factor(df_long_bar$XAXIS)))), 
                  y  = LINE * 40))  
   scale_y_continuous(sec.axis = sec_axis(~ . / 40))
  

Столбчатая диаграмма