将线分配到ggplot中的第二个y轴

时间:2019-03-19 09:45:07

标签: 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))

结果应如下所示(画线不基于数据,只是为了澄清):

enter image description here

  

如何将这条线放入图中?

2 个答案:

答案 0 :(得分:2)

问题是您的barplot适用于类别,而折线图应适用于数值。因此,您必须相应地转换x值。

您首先将XAXIS转换为一个因数(所有级别如df_long_bar所示),然后将其转换回数字。由于第二个轴最终仅是注解,因此您必须缩放LINE使其在 first 轴上正确显示。

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

Bar-Line-Chart

答案 1 :(得分:2)

您可以在最终数据框中尝试以下操作:

  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函数的默认值。

plot