3

I've searched for a solution to my problem but haven't been able to find one that directly answers my question. For example, I've seen: Combining Bar and Line chart (double axis) in ggplot2 and Bar Chart + Line Graph on One Plot with GGPlot and a couple others, and while they get close, they don't quite hit what I'm getting at.

I am trying to create a chart with two plots, one area plot and one line plot. The two plots share the y-axis. I've been trying to use both long and wide data frame formats but I can't get the chart to work while also producing a legend. I know that to get a legend, one would normally want to use long format and to specify the variable key as color = or fill =, but because I want each variable in a separate plot type, I see no way to get this done.

I have successfully created the chart I want, but it does not include the legend, and the code seems clunky. Can anyone provide some guidance? See below for my attempts. Data below examples.

Attempt 1: Long Format

library(tidyverse)
growthUR_long %>% 
  ggplot(aes(x = Date)) + 
  geom_area(data = (. %>% filter(growthUR_long$Type == "Growth")), aes(y = value), fill = "blue", color = "black") +
  labs(x = "Date", y = "Percent") + 
  geom_line(data = (. %>% filter(growthUR_long$Type == "UR")), aes(y = value), color = "black")

Long Output

Attempt 2: Wide Format

growthUR_wide %>%  
  ggplot(aes(x = Date)) + 
  geom_area(aes(y = Growth), fill = "blue", color = "black") +
  labs(x = "Date", y = "Percent") + 
  geom_line(aes(y = UR), color = "black")

Wide Output

Data

growthUR_long <- structure(list(Date = structure(c(16040, 16040, 16071, 16071, 
16102, 16102, 16130, 16130, 16161, 16161, 16191, 16191, 16222, 
16222, 16252, 16252, 16283, 16283, 16314, 16314, 16344, 16344, 
16375, 16375, 16405, 16405, 16436, 16436, 16467, 16467, 16495, 
16495, 16526, 16526, 16556, 16556, 16587, 16587, 16617, 16617, 
16648, 16648, 16679, 16679, 16709, 16709, 16740, 16740, 16770, 
16770, 16801, 16801, 16832, 16832, 16861, 16861, 16892, 16892, 
16922, 16922, 16953, 16953, 16983, 16983, 17014, 17014, 17045, 
17045, 17075, 17075, 17106, 17106, 17136, 17136, 17167, 17167, 
17198, 17198, 17226, 17226, 17257, 17257, 17287, 17287, 17318, 
17318, 17348, 17348, 17379, 17379, 17410, 17410, 17440, 17440, 
17471, 17471, 17501, 17501, 17532, 17532, 17563, 17563, 17591, 
17591, 17622, 17622, 17652, 17652, 17683, 17683, 17713, 17713, 
17744, 17744, 17775, 17775, 17805, 17805, 17836, 17836), class = "Date"), 
    Type = c("Growth", "UR", "Growth", "UR", "Growth", "UR", 
    "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR", "Growth", "UR", "Growth", "UR", "Growth", 
    "UR", "Growth", "UR"), value = c(0.0322086110094131, 0.0884577488042408, 
    0.0329947909338724, 0.0867061999760205, 0.0369791049661803, 
    0.0851919078232827, 0.0355169985403396, 0.0862978396964806, 
    0.0396692395382414, 0.0816915271432576, 0.0403342630003154, 
    0.08139558480318, 0.0353677807163653, 0.0801250617385394, 
    0.0348174892816639, 0.079246182084833, 0.0421586821845255, 
    0.0775132293815652, 0.045497159757506, 0.0762505497421263, 
    0.0479855163519212, 0.0756443010441955, 0.0431645807500451, 
    0.075679052359729, 0.0461836867149323, 0.0744676156513522, 
    0.0458201746505216, 0.0729279736217616, 0.0433054752282878, 
    0.0721403911270975, 0.0436767425553533, 0.070408204935737, 
    0.0405882652967209, 0.0703511470179263, 0.0391375049579188, 
    0.0690899407055714, 0.0393839156918634, 0.0690807060415389, 
    0.040776372038464, 0.0684442282747515, 0.0373001234501384, 
    0.0675339627652226, 0.0354219436836223, 0.0672348391519624, 
    0.0356159068524273, 0.0656551851245833, 0.039641088863388, 
    0.0647037939841651, 0.0399609996985248, 0.0635515287191864, 
    0.0317013278193472, 0.0630723444645541, 0.0328512011800204, 
    0.0620325823861175, 0.0327218554890207, 0.0614388558423061, 
    0.0334585785814081, 0.0609839998459472, 0.0308070913309046, 
    0.0597535514359257, 0.0338149386881423, 0.0591362192249516, 
    0.040317092357782, 0.0588051370066046, 0.034759613402543, 
    0.0566379922660853, 0.0394899239434814, 0.0563870883959305, 
    0.0314090340958895, 0.056679569373787, 0.0299952260614151, 
    0.0557285832378203, 0.0266744499962965, 0.054509993105507, 
    0.0356026530670595, 0.0541931717398106, 0.0342705188801191, 
    0.0539209138078119, 0.0357561213000237, 0.0534049405690803, 
    0.0282430112386445, 0.0538194547588392, 0.0320635214245448, 
    0.0535277334240149, 0.0294972674271483, 0.0532145449540054, 
    0.0254391816585626, 0.0521552584654269, 0.0251735156510164, 
    0.0514311178290782, 0.024173910868835, 0.0513899849245179, 
    0.0272327608151584, 0.0507680778938399, 0.0222257590529378, 
    0.0508044295844716, 0.0270204198555397, 0.0514736110118438, 
    0.0230437398194829, 0.0520862873603839, 0.0267092143066034, 
    0.0518027591652176, 0.0237249157033108, 0.0513989487830691, 
    0.0284997482684342, 0.0508771526917733, 0.0287893153050511, 
    0.0453979456228745, 0.0295347574671514, 0.045531549777798, 
    0.0385321606196869, 0.0454762717198563, 0.0394461559426129, 
    0.0471731715700883, 0.035513049515421, 0.0462938811890929, 
    0.0369998652281156, 0.0456567853126557, 0.0383561097442899, 
    0.0456830160674887)), row.names = c(NA, -120L), class = c("tbl_df", 
"tbl", "data.frame"))

growthUR_wide <- structure(list(Date = structure(c(16040, 16071, 16102, 16130, 
16161, 16191, 16222, 16252, 16283, 16314, 16344, 16375, 16405, 
16436, 16467, 16495, 16526, 16556, 16587, 16617, 16648, 16679, 
16709, 16740, 16770, 16801, 16832, 16861, 16892, 16922, 16953, 
16983, 17014, 17045, 17075, 17106, 17136, 17167, 17198, 17226, 
17257, 17287, 17318, 17348, 17379, 17410, 17440, 17471, 17501, 
17532, 17563, 17591, 17622, 17652, 17683, 17713, 17744, 17775, 
17805, 17836), class = "Date"), Growth = c(0.0322086110094131, 
0.0329947909338724, 0.0369791049661803, 0.0355169985403396, 0.0396692395382414, 
0.0403342630003154, 0.0353677807163653, 0.0348174892816639, 0.0421586821845255, 
0.045497159757506, 0.0479855163519212, 0.0431645807500451, 0.0461836867149323, 
0.0458201746505216, 0.0433054752282878, 0.0436767425553533, 0.0405882652967209, 
0.0391375049579188, 0.0393839156918634, 0.040776372038464, 0.0373001234501384, 
0.0354219436836223, 0.0356159068524273, 0.039641088863388, 0.0399609996985248, 
0.0317013278193472, 0.0328512011800204, 0.0327218554890207, 0.0334585785814081, 
0.0308070913309046, 0.0338149386881423, 0.040317092357782, 0.034759613402543, 
0.0394899239434814, 0.0314090340958895, 0.0299952260614151, 0.0266744499962965, 
0.0356026530670595, 0.0342705188801191, 0.0357561213000237, 0.0282430112386445, 
0.0320635214245448, 0.0294972674271483, 0.0254391816585626, 0.0251735156510164, 
0.024173910868835, 0.0272327608151584, 0.0222257590529378, 0.0270204198555397, 
0.0230437398194829, 0.0267092143066034, 0.0237249157033108, 0.0284997482684342, 
0.0287893153050511, 0.0295347574671514, 0.0385321606196869, 0.0394461559426129, 
0.035513049515421, 0.0369998652281156, 0.0383561097442899), UR = c(0.0884577488042408, 
0.0867061999760205, 0.0851919078232827, 0.0862978396964806, 0.0816915271432576, 
0.08139558480318, 0.0801250617385394, 0.079246182084833, 0.0775132293815652, 
0.0762505497421263, 0.0756443010441955, 0.075679052359729, 0.0744676156513522, 
0.0729279736217616, 0.0721403911270975, 0.070408204935737, 0.0703511470179263, 
0.0690899407055714, 0.0690807060415389, 0.0684442282747515, 0.0675339627652226, 
0.0672348391519624, 0.0656551851245833, 0.0647037939841651, 0.0635515287191864, 
0.0630723444645541, 0.0620325823861175, 0.0614388558423061, 0.0609839998459472, 
0.0597535514359257, 0.0591362192249516, 0.0588051370066046, 0.0566379922660853, 
0.0563870883959305, 0.056679569373787, 0.0557285832378203, 0.054509993105507, 
0.0541931717398106, 0.0539209138078119, 0.0534049405690803, 0.0538194547588392, 
0.0535277334240149, 0.0532145449540054, 0.0521552584654269, 0.0514311178290782, 
0.0513899849245179, 0.0507680778938399, 0.0508044295844716, 0.0514736110118438, 
0.0520862873603839, 0.0518027591652176, 0.0513989487830691, 0.0508771526917733, 
0.0453979456228745, 0.045531549777798, 0.0454762717198563, 0.0471731715700883, 
0.0462938811890929, 0.0456567853126557, 0.0456830160674887)), row.names = c(NA, 
-60L), class = c("tbl_df", "tbl", "data.frame"))
2
  • What exactly do you want in legend? UK and Growth?
    – pogibas
    Commented Jan 8, 2019 at 21:34
  • @PoGibas, thanks. Yes, UR and Growth.
    – hmhensen
    Commented Jan 8, 2019 at 21:34

2 Answers 2

7

You can use wide format and specify fill, color within aes. Then to get wanted color ("blue", "black") you can scale_(fill/color)_manual.

ggplot(growthUR_wide, aes(Date)) + 
    geom_area(aes(y = Growth, fill = "Growth"), color = "black") +
    geom_line(aes(y = UR, color = "UK"), size = 1.5) +
    labs(x = "Date", 
         y = "Percent", 
         fill = NULL, 
         color = NULL) +
    scale_color_manual(values = "black") +
    scale_fill_manual(values = "blue") +
    theme_classic()

enter image description here


More interesting solution (I'm maybe more correct from the data visualisation perspective) is to add annotation to your plot (I'm not that good with picking colors, you can decide yourself what goes best).

In this solution you annotate your layers with geom_text.

ggplot(growthUR_wide, aes(Date)) + 
    geom_area(aes(y = Growth), color = "black", fill = "thistle2") +
    geom_text(aes(growthUR_wide$Date[6], 0.02, label = "Growth"), 
              data.frame(), size = 10, color = "navyblue") +
    geom_text(aes(growthUR_wide$Date[15], 0.08, label = "UK"), 
              data.frame(), size = 10, color = "black") +
    geom_line(aes(y = UR), size = 1.5) +
    labs(x = "Date", 
         y = "Percent") +
    theme_classic()

enter image description here

1
  • Thanks for the answer. One follow-up question. How can I combine the two legends into one? Based on stackoverflow.com/questions/12410908/…, I'm trying something like this, but it's not working: ... + scale_color_manual(name = "Legend", labels = c("UR", "Job Growth"), values = c("black", "black")) + scale_fill_manual(name = "Legend", labels = c("UR", "Job Growth"), values = c("yellow", "yellow")).
    – hmhensen
    Commented Jan 9, 2019 at 2:04
2

I prefer @PoGibas's direct annotation approach instead of a legend. However, if a legend is necessary...

You can work with data in long format, which, as you note, is the more natural way to generate a legend, but you would need to convert Type to a factor and specify drop=FALSE in calls to scale_***_manual() so that both the fill and colour aesthetics will map legend colors to the same two levels of Type in each data subset. I've also reversed the legend order so that the legend order will match the physical location of the UR and Growth data in the plot area.

growthUR_long %>% 
  mutate(Type=factor(Type)) %>% 
  ggplot(aes(x = Date, y=value, fill=Type, colour=Type)) + 
    geom_area(data = (. %>% filter(growthUR_long$Type == "Growth")), colour="black") +
    geom_line(data = (. %>% filter(growthUR_long$Type == "UR"))) +
    labs(x = "Date", y = "Percent") + 
    scale_colour_manual(values=c("blue","red"), drop=FALSE) +
    scale_fill_manual(values=c("blue","red"), drop=FALSE) +
    guides(fill=guide_legend(reverse=TRUE),
           colour=guide_legend(reverse=TRUE)) +
    theme_bw()

enter image description here

1
  • 1
    Thanks for the answer. I went with @PoGibas' solution but yours is really useful for future reference too.
    – hmhensen
    Commented Jan 8, 2019 at 22:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.