I wanted to recreate a plot that I found on New York Times: 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)
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)?
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"))
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 = "")
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With