Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a geom line plot with single geom point at the end with legend

Tags:

r

ggplot2

I wanted to recreate a plot that I found on New York Times: enter image description here The dput data is:

structure(list(`Gss year for this respondent` = c(1977, 1977, 
                                                  1977, 1978, 1978, 1978, 1980, 1980, 1980, 1982, 1982, 1982, 1983, 
                                                  1983, 1983, 1984, 1984, 1984, 1985, 1985, 1985, 1987, 1987, 1987, 
                                                  1988, 1988, 1988, 1989, 1989, 1989, 1990, 1990, 1990, 1991, 1991, 
                                                  1991, 1993, 1993, 1993, 1994, 1994, 1994, 1996, 1996, 1996, 1998, 
                                                  1998, 1998, 2000, 2000, 2000, 2002, 2002, 2002, 2004, 2004, 2004, 
                                                  2006, 2006, 2006, 2008, 2008, 2008, 2010, 2010, 2010, 2012, 2012, 
                                                  2012, 2014, 2014, 2014, 2016, 2016, 2016, 2018, 2018, 2018), 
               `Political party affiliation` = c("Democrat", "Independent", 
                                                 "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                 "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                 "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                 "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                 "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                 "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                 "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                 "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                 "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                 "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                 "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                 "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                 "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                 "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                 "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                 "Republican"), value = c("Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
                                                                                                             "Yes", "Yes", "Yes", "Yes", "Yes"), n = c(226L, 191L, 130L, 
                                                                                                                                                       188L, 194L, 109L, 210L, 235L, 127L, 281L, 264L, 127L, 174L, 
                                                                                                                                                       200L, 139L, 176L, 220L, 140L, 200L, 192L, 147L, 285L, 227L, 
                                                                                                                                                       161L, 142L, 113L, 80L, 159L, 122L, 113L, 124L, 136L, 115L, 
                                                                                                                                                       142L, 127L, 129L, 180L, 161L, 112L, 351L, 311L, 207L, 306L, 
                                                                                                                                                       299L, 202L, 283L, 280L, 141L, 246L, 306L, 128L, 144L, 160L, 
                                                                                                                                                       77L, 138L, 121L, 80L, 307L, 290L, 156L, 214L, 198L, 117L, 
                                                                                                                                                       199L, 227L, 91L, 245L, 209L, 80L, 306L, 310L, 97L, 342L, 
                                                                                                                                                       337L, 127L, 300L, 333L, 96L), Percent = c(0.336, 0.38, 0.392, 
                                                                                                                                                                                                 0.311, 0.352, 0.306, 0.375, 0.419, 0.383, 0.327, 0.426, 0.363, 
                                                                                                                                                                                                 0.283, 0.37, 0.356, 0.324, 0.421, 0.381, 0.337, 0.416, 0.325, 
                                                                                                                                                                                                 0.352, 0.41, 0.385, 0.398, 0.334, 0.292, 0.407, 0.425, 0.333, 
                                                                                                                                                                                                 0.416, 0.455, 0.377, 0.409, 0.398, 0.419, 0.483, 0.445, 0.354, 
                                                                                                                                                                                                 0.485, 0.471, 0.375, 0.479, 0.421, 0.378, 0.427, 0.409, 0.295, 
                                                                                                                                                                                                 0.403, 0.407, 0.286, 0.462, 0.475, 0.307, 0.466, 0.382, 0.307, 
                                                                                                                                                                                                 0.488, 0.374, 0.293, 0.463, 0.396, 0.343, 0.49, 0.433, 0.312, 
                                                                                                                                                                                                 0.538, 0.421, 0.274, 0.536, 0.44, 0.271, 0.531, 0.461, 0.298, 
                                                                                                                                                                                                 0.607, 0.513, 0.283)), class = c("grouped_df", "tbl_df", 
                                                                                                                                                                                                                                  "tbl", "data.frame"), row.names = c(NA, -78L), groups = structure(list(
                                                                                                                                                                                                                                    `Gss year for this respondent` = c(1977, 1977, 1977, 1978, 
                                                                                                                                                                                                                                                                       1978, 1978, 1980, 1980, 1980, 1982, 1982, 1982, 1983, 1983, 
                                                                                                                                                                                                                                                                       1983, 1984, 1984, 1984, 1985, 1985, 1985, 1987, 1987, 1987, 
                                                                                                                                                                                                                                                                       1988, 1988, 1988, 1989, 1989, 1989, 1990, 1990, 1990, 1991, 
                                                                                                                                                                                                                                                                       1991, 1991, 1993, 1993, 1993, 1994, 1994, 1994, 1996, 1996, 
                                                                                                                                                                                                                                                                       1996, 1998, 1998, 1998, 2000, 2000, 2000, 2002, 2002, 2002, 
                                                                                                                                                                                                                                                                       2004, 2004, 2004, 2006, 2006, 2006, 2008, 2008, 2008, 2010, 
                                                                                                                                                                                                                                                                       2010, 2010, 2012, 2012, 2012, 2014, 2014, 2014, 2016, 2016, 
                                                                                                                                                                                                                                                                       2016, 2018, 2018, 2018), `Political party affiliation` = c("Democrat", 
                                                                                                                                                                                                                                                                                                                                  "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                                                                                                                                                                                                                                                                                                  "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                                                                                                                                                                                                                                                                                                  "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                                                                                                                                                                                                                                                                                                  "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                                                                                                                                                                                                                                                                                                  "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                                                                                                                                                                                                                                                                                                  "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                                                                                                                                                                                                                                                                                                  "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                                                                                                                                                                                                                                                                                                  "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                                                                                                                                                                                                                                                                                                  "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                                                                                                                                                                                                                                                                                                  "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                                                                                                                                                                                                                                                                                                  "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                                                                                                                                                                                                                                                                                                  "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                                                                                                                                                                                                                                                                                                  "Independent", "Republican", "Democrat", "Independent", "Republican", 
                                                                                                                                                                                                                                                                                                                                  "Democrat", "Independent", "Republican", "Democrat", "Independent", 
                                                                                                                                                                                                                                                                                                                                  "Republican", "Democrat", "Independent", "Republican", "Democrat", 
                                                                                                                                                                                                                                                                                                                                  "Independent", "Republican"), .rows = list(1L, 2L, 3L, 4L, 
                                                                                                                                                                                                                                                                                                                                                                             5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 
                                                                                                                                                                                                                                                                                                                                                                             17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 
                                                                                                                                                                                                                                                                                                                                                                             28L, 29L, 30L, 31L, 32L, 33L, 34L, 35L, 36L, 37L, 38L, 
                                                                                                                                                                                                                                                                                                                                                                             39L, 40L, 41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 
                                                                                                                                                                                                                                                                                                                                                                             50L, 51L, 52L, 53L, 54L, 55L, 56L, 57L, 58L, 59L, 60L, 
                                                                                                                                                                                                                                                                                                                                                                             61L, 62L, 63L, 64L, 65L, 66L, 67L, 68L, 69L, 70L, 71L, 
                                                                                                                                                                                                                                                                                                                                                                             72L, 73L, 74L, 75L, 76L, 77L, 78L)), row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                                                                                                                                -78L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))

The closest I've come is this:

GSStimeany6 %>%
  ggplot(aes(x = `Gss year for this respondent`,
             y = Percent,
             fill = `Political party affiliation`)) +
  geom_line(aes(color = `Political party affiliation`),
            size = 1) +
  geom_point() +
  ylab("")+
  ylim(0,80)

enter image description here

How can I get the geom point to only work on the last point (and be the same color as the geom line), and have the legend show up next to that point (so the end of the Democrat point would have a blue dot and have the Democrat text show up next to it)?

like image 913
Pedro Guizar Avatar asked Dec 23 '19 22:12

Pedro Guizar


2 Answers

For geom_point and geom_text, you can subset your dataframe by keeping only the last year (2018):

ggplot(df, aes(x = `Gss year for this respondent`, y = Percent*100))+
  geom_line(aes(color = `Political party affiliation`), show.legend = FALSE)+
  geom_point(data = df[df$`Gss year for this respondent` == max(df$`Gss year for this respondent`),],
             aes(x =`Gss year for this respondent`, y = Percent*100, color = `Political party affiliation`), show.legend = FALSE)+
  geom_text(data = df[df$`Gss year for this respondent` == max(df$`Gss year for this respondent`),],
            aes(x =`Gss year for this respondent`, 
                y = Percent*100, 
                colour = `Political party affiliation`,
                label = `Political party affiliation`), show.legend = FALSE, hjust = -0.1)+
  xlim(1975, 2026)+
  ylim(0,80)+
  scale_color_manual(values = c("blue","green","red"))

enter image description here

like image 139
dc37 Avatar answered Sep 21 '22 14:09

dc37


Here are a few updates to @dc37's answer that get OP closer to desired plot. To be clear, @dc37's answer solves the main problem: how to plot just the final dot in the series. All of this was too much to add as a comment to @dc37's answer, so I'm posting it as a separate solution - although it's really more an extension of @dc37's answer, rather than a distinct alternative.

Updates

  • Fixes x-axis range so that annotations occur after axis stops

  • Removes color from annotations

  • Eliminates space between x-axis line and y=0 on plot

  • Creates space around x-axis tick marks (space between axis line and tick text)

  • Major y-axis grid lines displayed

  • Made x- and y- ticks match the original

    ggplot(df, aes(x = `Gss year for this respondent`, y = Percent*100, 
               color = `Political party affiliation`)) +
    geom_line(show.legend = FALSE, size = 1) +
    geom_point(data = point_df, aes(x =`Gss year for this respondent`), 
               show.legend = FALSE, size = 2) +
    scale_x_continuous(breaks = seq(1980, 2015, by = 5)) +
    scale_y_continuous(limits = c(0, 80), 
                       breaks = seq(0, 80, by = 20),
                       expand = c(0, 0)) +
    scale_color_manual(values = c("deepskyblue1","gray80","firebrick3")) +
    geom_text(data = point_df,
              aes(x = 2019, y = Percent*100, 
                  label = `Political party affiliation`), 
              color = "black",
              show.legend = FALSE, 
              hjust = -0.1) +
    coord_cartesian(xlim = c(1978, 2016), clip = 'off') +
    theme(plot.margin = unit(c(1,7,1,1), "lines"),
          panel.grid.major.y = element_line(color = "gray90"),
          axis.line.y = element_blank(),
          axis.ticks.length.x = unit(.3, units = "cm"),
          axis.ticks.x = element_line(linetype = 2)) +
    labs(y = "", x = "")  
    

    plot

Important
The graph produced from OP's data - replicated in OP's code, as well as this answer and @dc37's answer - looks slightly different than the original screenshot. (Look at how the lines don't overlap each other in the same way.) I haven't dug into this - the updates here are focused on cosmetics.

like image 20
andrew_reece Avatar answered Sep 18 '22 14:09

andrew_reece