4

I want to use qplot (ggplot2) and then forward the data with magrittr:

This works:

mtcars %>% qplot(mpg, cyl, data=.)

This produces an error:

mtcars %>% qplot(mpg, cyl, data=.) %>% summarise(mean(mpg))

And those produce only summary statistics:

mtcars %T>% qplot(mpg, cyl, data=.) %>% summarise(mean(mpg))
mtcars %>% {qplot(mpg, cyl, data=.); .} %>% summarise(mean(mpg))
mtcars %T>% {qplot(mpg, cyl, data=.)} %>% summarise(mean(mpg))

What is the problem? I already found this solution, but it does not help, as you see from the code attached.

Community
  • 1
  • 1
Tim
  • 7,075
  • 6
  • 29
  • 58
  • It seems youre passing the ggplot object. Is it possible to apply summarise in the ggplot object? – zelite Dec 04 '14 at 14:15
  • 1
    but `%T>%` or `%>% {f(.); .}` do not pas the resulting object along but return the imput object (see: http://blog.rstudio.org/2014/12/01/magrittr-1-5/). – Tim Dec 04 '14 at 14:16
  • 1
    what about: `mtcars %>% {print(qplot(mpg, cyl, data=.)); .} %>% summarise(mean(mpg))` ? is that what you want? Maybe related to: http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-lattice_002ftrellis-graphics-not-work_003f – zelite Dec 04 '14 at 14:18
  • 1
    Yes! The question is: why it does not work without print..? – Tim Dec 04 '14 at 14:21

2 Answers2

6

All ggplot2 functions return an object that represents a plot - to see it you need to print it. That normally happens automatically when you're working in the console, but needs to explicit inside a function or a chain.

The most elegant solution I could come up with is this:

library("ggplot2")
library("magrittr")
library("dplyr")

echo <- function(x) {
  print(x)
  x
}
mtcars %>% 
  {echo(qplot(mpg, cyl, data = .))} %>% 
  summarise(mean(mpg))

It seems like there should be a better way.

hadley
  • 102,019
  • 32
  • 183
  • 245
  • Thanks! It really asks for a better solution since you encourage to combine `magrittr`, `dplyr` and `ggplot2`, and `magritr` 1.5 `%T>$` is less effective if you have to use this kind of tricks to make it work for plotting. – Tim Dec 04 '14 at 15:11
  • @Tim The example seems forced to me because usually the plot is the last thing in the pipe. – hadley Dec 04 '14 at 15:40
  • Actually this is real life one (simplified): `get data -> plot summaries -> group and rearrange -> compute some statistics etc.` In this case plot's role was for preliminary data check. – Tim Dec 04 '14 at 16:42
  • 1
    A little simpler: `mtcars %T>% { print(qplot(mpg, cyl, data = .)) } %>% summarise(mean(mpg))` or alternatively `mtcars %T>% { summarise(., mean(mpg)) %>% print ; } %>% qplot(mpg, cyl, data = .)`. The latter is more in-line with the comment by @hadley about keeping the plot at the end of the pipe. – r2evans Dec 04 '14 at 18:26
  • I submitted a feature request to the magritr package at https://github.com/tidyverse/magrittr/issues/140 something like %g>% would probably make this easier. – Jerry T Feb 01 '17 at 16:53
2

This seems more clean to me, because it does not require using %T>% (which IMHO makes a pipe harder to re-arrange and read) and no {} around the expression to avoid passing the object there. I'm not sure how much harm there is in passing the object and ignoring it.

I've never had a use for the %T>% tee where I didn't also want to print or plot. And I never wanted to print/plot the object being piped itself (usually a big dataset). So I never use %T>%.

library("ggplot2")
library("dplyr")


pap = function(pass, to_print = NULL, side_effect = NULL) {
  if( !is.null(to_print)) {
    if (is.function(to_print)) {
      print(to_print(pass))
    } else {
      print(to_print)
    }
  }
  side_effect
  invisible(pass)
}

mtcars  %>% 
   pap(summary) %>% 
   pap(side_effect = plot(.)) %>% 
   pap(qplot(mpg, cyl, data = .)) %>% 
   summarise(mean(mpg))

I usually don't use plotting as side-effect in my pipes, so the solution above works best for me (requires "extra typing" for side-effect plot). I'd like to be able to disambiguate between these intended scenarios (e.g. plot vs. qplot) automatically, but haven't found a reliable way.

Ruben
  • 3,452
  • 31
  • 47