ggplot2
предпочитает вещи в длинном формате и имеет тенденцию «puni sh» (усложнять), делая то, что вы делаете сейчас. Давайте изменим форму (я буду использовать tidyr::pivot_longer
, другие будут работать так же).
library(ggplot2)
ggplot(tidyr::pivot_longer(df, Fcst1:Fcst4),
aes(Date, value, color = name)) +
geom_line()
As you can tell, using color=
within an aes
thetic varies the colors accordingly. If you want to control the colors, there are many themes available (e.g., viridis
and many with color-blind profiles), but doing it manually is done with scale_color_manual
, I'll demo below. Finally, I'll tweak the names and such a little.
ggplot(tidyr::pivot_longer(df, Actual:Fcst4, names_to = "Forecast", names_prefix = "Fcst"),
aes(Date, value, color = Forecast)) +
geom_line(size = 1) +
scale_color_manual(values = c("Actual" = "black", "1" = "red", "2" = "blue",
"3" = "green", "4" = "yellow", "5" = "purple",
"6" = "orange")) +
ggtitle(label = "Actuals vs 2015 Forecasts", subtitle = "(unk filename)") +
ylab("Balance") +
scale_y_continuous(labels = scales::comma)
Ручные цвета не обязательно быть идеальным совпадением, как вы можете видеть, если 5
определено, но не используется (на основе вашей выборки данных). Отсутствующие цвета в названном векторе values=
будут удалены с графика (с предупреждением).
Finally, a common question is ordering the components in the legend. This can be done with factor
s:
df_long <- tidyr::pivot_longer(df, Actual:Fcst4, names_to = "Forecast", names_prefix = "Fcst")
df_long$Forecast <- relevel(factor(df_long$Forecast), "Actual")
ggplot(df_long, aes(Date, value, color = Forecast)) +
geom_line(size = 1) +
scale_color_manual(values = c("Actual" = "black", "1" = "red", "2" = "blue",
"3" = "green", "4" = "yellow", "5" = "purple",
"6" = "orange")) +
ggtitle(label = "Actuals vs 2015 Forecasts", subtitle = "(unk filename)") +
ylab("Balance") +
scale_y_continuous(labels = scales::comma)
I used stats::relevel
to move one factor "to the front", otherwise it tends to be alphabetic (as shown in the second graphic above). There are many tools for working with factors, the forcats
package is a popular one (esp among tidyverse users).
This processing could easily have been handled within a dplyr
-pipe.
Since you mentioned plotting batches of forecasts at a time, here are a couple of approaches. I'll augment the data by copying the Fcst
columns into another set of 4:
df <- cbind(df, setNames(df[,3:6], paste0("Fcst", 5:8)))
df_long <- tidyr::pivot_longer(df, Actual:Fcst8, names_to = "Forecast", names_prefix = "Fcst")
df_long$Forecast <- relevel(factor(df_long$Forecast), "Actual")
Я «упросту» график для краткости кода, хотя тематика по-прежнему будет работать, как указано выше.
Отдельные графики, фильтровать по одному и строить график ит.
ggplot(df_long[df_long$Forecast %in% c("Actual", "1", "3", "5", "7"),],
aes(Date, value, color = Forecast)) +
geom_line(size = 1)
Фацетирование. Я покажу метод грубой силы для этого примера, а затем более гибкий (возможно) способ. Я использую здесь dplyr
, потому что он упрощает просмотр и понимание некоторых операций (как только вы привыкнете к синтаксису dplyr-esque). (Я часто нахожу, что сохранение контрольной линии «Фактическое», другого цвета / толщины, чем у других, помогает укрепить сравнения по граням. Перед вами.)
library(dplyr)
df_rest <- df_long %>%
filter(! Forecast == "Actual") %>%
mutate(grp = cut(as.integer(as.character(Forecast)), c(0, 5, 9), labels = FALSE))
df_combined <- df_long %>%
filter(Forecast == "Actual") %>%
select(-grp) %>%
crossing(., unique(select(df_rest, grp))) %>%
bind_rows(df_rest)
ggplot(df_combined, aes(Date, value, color = Forecast)) +
geom_line(size = 1) +
facet_grid(grp ~ .)
Faceting, but with a more maintainable set of facets. I'll use a simple data.frame
to control which lines are included in which $grp
. This makes it much easier (imo) to "cherry pick" specific lines for specific facets.
grps <- tibble::tribble(
~grp, ~Forecast
,1, "Actual"
,1, "1"
,1, "3"
,1, "5"
,2, "Actual"
,2, "2"
,2, "4"
,2, "6"
,2, "7"
,2, "8"
)
ggplot(left_join(df_long, grps, by = "Forecast"),
aes(Date, value, color = Forecast)) +
geom_line(size = 1) +
facet_grid(grp ~ .)
В этом случае я использовал tribble
исключительно для того, чтобы было легче увидеть, что идет вместе; любой data.frame
будет работать. Я также демонстрирую, что $grp
размеры не обязательно должны быть равными, включая все, что вы хотите.
Используйте рамку из # 3 выше для соединения, а затем просто отфильтруйте их, как в
left_join(df_long, grps, by = "Forecase") %>%
filter(grp == 1) %>%
ggplot(., aes(Date, value, color = Forecast)) +
geom_line(size = 1) +
facet_grid(grp ~ .)