Reputation: 749
I am making line graphs using geom_smooth
and labelling it using geom_dl
. The lines also have geom_points
as an additional display. The texts are positioned on the points and I want the text to be positioned on the tails of the smooth lines. My code is given as below.
library(ggplot2)
library(directlabels)
ggplot(gedu5, aes(x = Year, y = gedu, colour = Country, group = Country)) +
geom_smooth(method = "lm", formula = y ~ poly(x, 3), se = FALSE)+
geom_point(stat = "identity") +
scale_colour_discrete(guide = 'none') +
geom_dl(aes(label = Country), method = list(dl.combine("first.points", "last.points"), cex = 1)) +
labs(title = "Government expenditure on education, total (% of GDP)", cex.main = 2.5) +
theme(axis.title = element_blank()) +
facet_wrap(.~Region, 2, scales="free")
The Image it renders is given as below. As you can see in the image that labels are actually pegged on the points and not on the lines. I want to stick the labels to the lines and not to the points.
The data for the above image is here:
structure(list(Year = c(1998L, 1999L, 2000L, 2001L, 2002L, 2003L,
2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L,
2013L, 2014L, 2015L, 2016L, 2017L, 1998L, 1999L, 2000L, 2001L,
2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L,
2011L, 2012L, 2013L, 2014L, 2015L, 2016L, 2017L, 1998L, 1999L,
2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L,
2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 2015L, 2016L, 2017L,
1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L,
2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 2015L,
2016L, 2017L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L,
2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L,
2014L, 2015L, 2016L, 2017L, 1998L, 1999L, 2000L, 2001L, 2002L,
2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L,
2012L, 2013L, 2014L, 2015L, 2016L, 2017L, 1998L, 1999L, 2000L,
2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L,
2010L, 2011L, 2012L, 2013L, 2014L, 2015L, 2016L, 2017L, 1998L,
1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L,
2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 2015L, 2016L,
2017L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L,
2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L,
2015L, 2016L, 2017L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L,
2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L,
2013L, 2014L, 2015L, 2016L, 2017L, 1998L, 1999L, 2000L, 2001L,
2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L,
2011L, 2012L, 2013L, 2014L, 2015L, 2016L, 2017L, 1998L, 1999L,
2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L,
2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 2015L, 2016L, 2017L,
1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L,
2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 2015L,
2016L, 2017L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L,
2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L,
2014L, 2015L, 2016L, 2017L, 1998L, 1999L, 2000L, 2001L, 2002L,
2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L,
2012L, 2013L, 2014L, 2015L, 2016L, 2017L, 1998L, 1999L, 2000L,
2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L,
2010L, 2011L, 2012L, 2013L, 2014L, 2015L, 2016L, 2017L, 1998L,
1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L,
2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 2015L, 2016L,
2017L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L,
2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L,
2015L, 2016L, 2017L), Country = c("Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Bangladesh", "Bangladesh",
"Bangladesh", "Bangladesh", "Bangladesh", "Bangladesh", "Bangladesh",
"Bangladesh", "Bangladesh", "Bangladesh", "Bangladesh", "Bangladesh",
"Bangladesh", "Bangladesh", "Bangladesh", "Bangladesh", "Bangladesh",
"Bangladesh", "Bangladesh", "Bangladesh", "Bhutan", "Bhutan",
"Bhutan", "Bhutan", "Bhutan", "Bhutan", "Bhutan", "Bhutan", "Bhutan",
"Bhutan", "Bhutan", "Bhutan", "Bhutan", "Bhutan", "Bhutan", "Bhutan",
"Bhutan", "Bhutan", "Bhutan", "Bhutan", "India", "India", "India",
"India", "India", "India", "India", "India", "India", "India",
"India", "India", "India", "India", "India", "India", "India",
"India", "India", "India", "Maldives", "Maldives", "Maldives",
"Maldives", "Maldives", "Maldives", "Maldives", "Maldives", "Maldives",
"Maldives", "Maldives", "Maldives", "Maldives", "Maldives", "Maldives",
"Maldives", "Maldives", "Maldives", "Maldives", "Maldives", "Nepal",
"Nepal", "Nepal", "Nepal", "Nepal", "Nepal", "Nepal", "Nepal",
"Nepal", "Nepal", "Nepal", "Nepal", "Nepal", "Nepal", "Nepal",
"Nepal", "Nepal", "Nepal", "Nepal", "Nepal", "Pakistan", "Pakistan",
"Pakistan", "Pakistan", "Pakistan", "Pakistan", "Pakistan", "Pakistan",
"Pakistan", "Pakistan", "Pakistan", "Pakistan", "Pakistan", "Pakistan",
"Pakistan", "Pakistan", "Pakistan", "Pakistan", "Pakistan", "Pakistan",
"Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka",
"Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka",
"Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka",
"Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka", "Sri_Lanka",
"World", "World", "World", "World", "World", "World", "World",
"World", "World", "World", "World", "World", "World", "World",
"World", "World", "World", "World", "World", "World", "South_Asia",
"South_Asia", "South_Asia", "South_Asia", "South_Asia", "South_Asia",
"South_Asia", "South_Asia", "South_Asia", "South_Asia", "South_Asia",
"South_Asia", "South_Asia", "South_Asia", "South_Asia", "South_Asia",
"South_Asia", "South_Asia", "South_Asia", "South_Asia", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Sub.Saharan_Africa", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Sub.Saharan_Africa", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Sub.Saharan_Africa", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Sub.Saharan_Africa", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Sub.Saharan_Africa", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Sub.Saharan_Africa", "Sub.Saharan_Africa",
"Sub.Saharan_Africa", "Middle_income", "Middle_income", "Middle_income",
"Middle_income", "Middle_income", "Middle_income", "Middle_income",
"Middle_income", "Middle_income", "Middle_income", "Middle_income",
"Middle_income", "Middle_income", "Middle_income", "Middle_income",
"Middle_income", "Middle_income", "Middle_income", "Middle_income",
"Middle_income", "Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Central_Europe_and_the_Baltics", "Central_Europe_and_the_Baltics",
"Euro_area", "Euro_area", "Euro_area", "Euro_area", "Euro_area",
"Euro_area", "Euro_area", "Euro_area", "Euro_area", "Euro_area",
"Euro_area", "Euro_area", "Euro_area", "Euro_area", "Euro_area",
"Euro_area", "Euro_area", "Euro_area", "Euro_area", "Euro_area",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Middle_East_North_Africa",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Middle_East_North_Africa",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Middle_East_North_Africa",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Middle_East_North_Africa",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Middle_East_North_Africa",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Middle_East_North_Africa",
"Middle_East_North_Africa", "Middle_East_North_Africa", "Latin_America_Caribbean",
"Latin_America_Caribbean", "Latin_America_Caribbean", "Latin_America_Caribbean",
"Latin_America_Caribbean", "Latin_America_Caribbean", "Latin_America_Caribbean",
"Latin_America_Caribbean", "Latin_America_Caribbean", "Latin_America_Caribbean",
"Latin_America_Caribbean", "Latin_America_Caribbean", "Latin_America_Caribbean",
"Latin_America_Caribbean", "Latin_America_Caribbean", "Latin_America_Caribbean",
"Latin_America_Caribbean", "Latin_America_Caribbean", "Latin_America_Caribbean",
"Latin_America_Caribbean", "North_America", "North_America",
"North_America", "North_America", "North_America", "North_America",
"North_America", "North_America", "North_America", "North_America",
"North_America", "North_America", "North_America", "North_America",
"North_America", "North_America", "North_America", "North_America",
"North_America", "North_America", "Low_income", "Low_income",
"Low_income", "Low_income", "Low_income", "Low_income", "Low_income",
"Low_income", "Low_income", "Low_income", "Low_income", "Low_income",
"Low_income", "Low_income", "Low_income", "Low_income", "Low_income",
"Low_income", "Low_income", "Low_income"), gedu = c(3.5, 3.8,
3.7, 3.3, 2.9, 2.6, 2.7, 3, 3.4, 3.7, 3.8, 3.7, 3.5, 3.5, 2.6,
3.5, 3.7, 3.3, 4.2, 4.1, 2.1, 2.1, 2.1, 2.2, 2, 2.1, 1.9, 2.1,
2.1, 2.2, 2, 1.9, 2, 2.1, 2.2, 2, 1.5, 1.3, 1.5, 2.5, 5.5, 5.7,
5.5, 5.7, 6.2, 6.8, 6.4, 7.1, 5.4, 4.8, 4.8, 4.6, 4, 4.7, 5.5,
5.6, 5.9, 7.3, 6.8, 7, 3.6, 4.4, 4.3, 4.2, 4, 3.6, 3.4, 3.2,
3.1, 3.2, 3.1, 3.3, 3.4, 3.8, 3.9, 3.8, 3.7, 3.9, 3.9, 3.8, 5.8,
5.5, 4.9, 4.7, 5.8, 5.3, 4.7, 5, 4.7, 4.4, 4.5, 5.8, 4.1, 3.5,
3.8, 3.8, 3.5, 4.4, 4.1, 4.1, 2.9, 2.9, 3, 3.7, 3.1, 3.1, 3.2,
3.4, 3.6, 3.5, 3.8, 4.7, 3.6, 3.8, 3.8, 3.5, 4, 3.7, 4.4, 5.5,
2.6, 2.6, 1.8, 1.5, 1.6, 1.9, 2, 2.2, 2.6, 2.6, 2.8, 2.6, 2.3,
2.2, 2.1, 2.5, 2.5, 2.6, 3, 2.9, 3, 5.2, 6.6, 7.3, 7.5, 7.2,
6.6, 5.7, 4.7, 3.7, 2.8, 2.1, 1.7, 1.8, 1.5, 1.6, 1.9, 2.2, 3.5,
2.8, 4.2, 4.2, 3.9, 4, 4, 4.1, 4, 4.1, 4.2, 4.2, 4.3, 4.7, 4.5,
4.3, 4.3, 4.6, 4.6, 4.7, 4.5, 4.5, 3, 2.8, 2.5, 2.8, 3.2, 3.1,
2.6, 3.2, 2.9, 2.6, 2.8, 2.6, 3.4, 2.8, 2.4, 3, 3.1, 3, 3.5,
2.9, 3.3, 3.3, 3.1, 3.4, 3.1, 3.2, 3.3, 3.6, 3.6, 3.5, 3.6, 3.9,
3.8, 3.9, 4.1, 4, 4.3, 4.5, 3.9, 4.5, 4.1, 4.1, 3.6, 3.7, 3.4,
3.6, 3.5, 3.9, 3.9, 3.6, 4, 4.5, 4.5, 4, 4.2, 4.3, 4.4, 4.3,
4.2, 4.4, 5, 4.6, 4.9, 5.1, 5.2, 5.1, 4.9, 4.8, 4.7, 4.6, 4.8,
5, 4.8, 4.6, 4.5, 4.6, 4.6, 4.8, 4.7, 4.7, 4.5, 4.8, 4.6, 5.2,
5.3, 5.1, 5, 5, 4.8, 4.7, 5.1, 5.6, 5.5, 5.1, 5, 5.3, 5.3, 4.9,
4.8, 4.8, 6.2, 6.3, 6.3, 6.2, 6.1, 6, 5.4, 5.6, 4.3, 5.2, 4.5,
4.7, 4.5, 4.4, 4.2, 4.2, 4.1, 4.2, 4.3, 4.5, 3.3, 3.8, 3.8, 3.8,
3.9, 3.5, 3.8, 3.9, 3.8, 3.9, 4.6, 5.3, 4.7, 4.4, 4.4, 5, 5.3,
4.9, 4.5, 4.5, 5.5, 5.5, 5.4, 5, 5, 5, 5, 4.8, 4.8, 4.8, 4.6,
4.8, 5.4, 5.3, 5.3, 4.9, 5, 5, 4.9, 5, 3.2, 3.2, 2.9, 3.3, 3.4,
3.2, 3.1, 3.1, 3.3, 3.4, 3.4, 3.5, 3.5, 3.8, 3.8, 3.1, 3.3, 3.8,
3.1, 3.5), Region = c("South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "South Asia", "South Asia", "South Asia",
"South Asia", "South Asia", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region",
"Region", "Region", "Region", "Region", "Region", "Region", "Region"
)), row.names = c(NA, -360L), class = "data.frame")
Upvotes: 1
Views: 374
Reputation: 9087
This is a way to do it by creating a custom method
for directlabels
.
Custom methods are functions with parameters d
and ...
which return a data frame. d
is a data frame with x
, y
, groups
and a few other columns.
Create a custom method that creates the lm
for each group. Keep the first and last values and set the hjust
appropriately.
library(tidyverse)
library(directlabels)
first_last_poly3 <- function(d, ...) {
d %>%
group_by(groups) %>%
group_modify(function(g, ...) {
mutate(g, y = predict(lm(y ~ poly(x, 3), data = g)))
}) %>%
filter(row_number() %in% c(1, n())) %>%
mutate(hjust = ifelse(row_number() == 1, 1, 0))
}
Create the plot and use first_last_poly3
as the geom_dl
method
.
ggplot(gedu5, aes(x = Year, y = gedu, colour = Country, group = Country)) +
geom_smooth(method = "lm", formula = y ~ poly(x, 3), se = FALSE)+
geom_point(stat = "identity") +
scale_colour_discrete(guide = 'none') +
geom_dl(aes(label = Country), method = first_last_poly3) +
labs(title = "Government expenditure on education, total (% of GDP)", cex.main = 2.5) +
theme(axis.title = element_blank()) +
facet_wrap(.~Region, 2, scales="free")
Upvotes: 1
Reputation: 123783
The issue is that geom_dl
uses the value of gedu
in your dataset and not the fitted values computed by geom_smooth
.
I tried
passing stat="smooth"
to geom_dl
which resulted in no labels appearing on the plot
adding labels at the endpoints manually using stat_smooth
with geom="text"
which however did not work
Therefore the only solution I could figure out is to compute the fitted values manually which can then be mapped on y
in geom_dl
. For computing the fittes values I
tidyr::nest
the df by Country
and Region
purrr::map
and broom::augment
to do the estimation and to get the fitted valuestidyr::unnest
and keep only the desired columnslibrary(ggplot2)
library(directlabels)
library(purrr)
library(broom)
library(tidyr)
library(dplyr)
gedu5 %>%
# Manually compute the fitted values
nest(data = -c(Region, Country)) %>%
mutate(mod = map(data, ~ lm(gedu ~ poly(Year, 3), data = .x)),
mod = map2(mod, data, augment)) %>%
unnest(mod) %>%
select(Country, Region, Year, gedu, .fitted) %>%
ggplot(aes(x = Year, y = gedu, colour = Country, group = Country)) +
geom_smooth(method = "lm", formula = y ~ poly(x, 3), se = FALSE) +
geom_dl(aes(y = .fitted, label = Country), method = list(dl.combine("first.points", "last.points"), cex = 1)) +
geom_point(stat = "identity") +
scale_colour_discrete(guide = "none") +
labs(title = "Government expenditure on education, total (% of GDP)", cex.main = 2.5) +
theme(axis.title = element_blank()) +
facet_wrap(.~Region, 2, scales="free")
Upvotes: 1