TITLE: Display line segments with given slope in ggplot2
DATE: 2020-09-05
AUTHOR: John L. Godlee
====================================================================


A question popped up online, where the user wanted to create a plot 
identical to this one, in R:

  ![Scatter plot of GDP per 
country](https://johngodlee.xyz/img_full/ggplot_segment/gdp.png)

The plot puts GDP per capita against mean life satisfaction, with 
an added third variable showing to what extent that mean life 
satisfaction is split equally among high and low income people. 
Every point has a slope line where the greater the slope, the 
higher the disparity in life satisfaction between high and low 
income people.

ggplot2 can use geom_abline() to calculate lines with slopes, but 
these lines traverse the entire plot, which isn't what we need 
here. geom_segment() can be used to calculate line segments, but 
only takes line end point coordinates as input. I wrote a simple 
function which calculates these end points from a known midpoint 
and slope, with some styling to allow for line segments of 
different lengths:

    library(ggplot2)

    dat <- data.frame(x = seq(1,4), y = seq(1,4), 
      slope = seq(0.5, by = 0.5, length.out = 4))

    endPoints <- function(x, y, m, d) {
      k <- d / sqrt(1 + (m^2))
      xmin <- x - k
      xmax <- x + k
      ymin <- y - (m * k)
      ymax <- y + (m * k)

      return(data.frame(xmin, ymin, xmax, ymax))
    }

    dat_end <- cbind(dat, endPoints(dat$x, dat$y, dat$slope, 0.1))

    ggplot() + 
      geom_point(data = dat_end, aes(x = x, y = y), colour = 
"blue") +
      geom_segment(data = dat_end, aes(x = xmin, xend = xmax, y = 
ymin, yend = ymax))

The function basically just re-writes the following equation to 
find x and y:

    (x \pm \frac{D}{\sqrt{1 + m^2}}, y \pm m \frac{D}{\sqrt{1 + 
m^2}})

This produces a plot like this:

  ![Example of function 
output](https://johngodlee.xyz/img_full/ggplot_segment/example.png)