ggplot2 Tufte lines same as axis ticks
Asked Answered
W

2

7

I used Tufte lines with ggplot2 for years now, but I've always wondered if there was an automated way to draw them, so they correspond to axis tics.

The usual way I draw them is like this :

ggplot(mtcars, aes(x=mpg, y=cyl))+
geom_bar(stat = "identity")+
theme_tufte()+
geom_hline(yintercept = c(5,10,15), col="white", lwd=3)

Tufte lines

Here I specify the ticks with yintercept = c(5,10,15), but recently I was building a Shiny app with changing axes, so I can't specify fixed ticks.

Is there a way for me to say something like yintercept = tickmarks, so that my Shiny app will always work without precalculating and defining both the axis and the Tufte lines manually?

Wooded answered 7/5, 2017 at 16:16 Comment(0)
I
6

You can use ggplot_build to extract the tickmark positions as a vector and then pass that to the yintercept argument of geom_hline:

p <- ggplot(mtcars, aes(x=mpg, y=cyl))+
    geom_bar(stat = "identity")+
    theme_tufte()

tickmarks <- ggplot_build(p)$layout$panel_ranges[[1]]$y.major_source  

p + geom_hline(yintercept = tickmarks, col="white", lwd=3)
Ibnsaud answered 7/5, 2017 at 16:45 Comment(1)
Thanks. This was exactly what I was looking for. Though eipi10's solution works as well. I wonder why this option isn't implemented in the core function.Wooded
F
5

Here's a function that calculates the break positions and then applies them to both scale_y_continuous and geom_hline:

library(ggthemes)
library(scales)
library(lazyeval)
library(tidyverse)

fnc = function(data, x, y, nbreaks=5, lwd=3, breaks=NULL) {

  if(is.null(breaks)) {
    breaks = data %>% group_by_(x) %>% 
      summarise_(yvar=interp(~ sum(yy), yy=as.name(y)))

    breaks = pretty_breaks(n=nbreaks)(c(0, breaks$yvar))
  }

  ggplot(data, aes_string(x, y)) +
   geom_bar(stat = "identity") +
   theme_tufte() +
   scale_y_continuous(breaks=breaks) +
   geom_hline(yintercept = breaks, col="white", lwd=lwd)
}

Now test out the function:

fnc(mtcars, "mpg", "cyl") 
fnc(mtcars, "mpg", "cyl", nbreaks=2)

fnc(iris, "Petal.Width", "Petal.Length", breaks=seq(0,80,20))
fnc(iris, "Petal.Width", "Petal.Length", nbreaks=6, lwd=1)

enter image description here

Finnish answered 7/5, 2017 at 16:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.