4

I like the idea of the pipe improving readability, but I've had difficulty using it because of how inflexible it feels. So far I've only succeeded when my goal is to straightforwardly pipe X through a set of functions h(g(f(x,foo),bar),stuff)

x %>%
f(foo) %>%
g(bar) %>%
h(stuff)

If I want to store an intermediate output so that I can have h(x,stuff,f(x,foo)), is that possible? I've tried

x %>% 
intermediate = f(foo) %>% 
g(bar)

but that fails. Assign doesn't work because the first argument is the name rather than the value; is there an opposite equivalent?

I know you can use "." to refer to x or portions of it multiple times, but is there a way to use only a portion of it initially? I want to perform different functions on different columns, such as

data.frame(x[,1],apply(.[,2:3],2,fun1),apply(.[,4],2,fun2))

but I can't figure out how to limit the first argument to only x[,1] instead of all of x. I can't use %>% select(1) %>% because then it will drop the rest forever. Is there a way to do this or should I just end the pipe, do these functions, and start another pipeline? Is the easiest solution to just put all of x into the data frame and then %>% select(1,5:9) %>%?

  • 3
    To do intermediate steps use `%T>%`. You may need to load magrittr first. Also, you might need to use `{}` around it like `x %T>% {bah <- .} %>% more_stuff` . – Frank Feb 23 '17 at 17:18
  • 1
    [Have a look at the `magrittr` readme](https://github.com/tidyverse/magrittr). – Gregor Thomas Feb 23 '17 at 17:23
  • 2
    Break it into two chains: `BOD %>% round(0) -> temp; temp %>% log` Also try: `anscombe %>% { data.frame(A = .[,1], B = apply(.[,2:3],1,sum), C = apply(.[,4,drop = FALSE],1,sum)) }` – G. Grothendieck Feb 23 '17 at 17:57
  • Also, this works `BOD %>% { round(., 0) -> temp } %>% log` – G. Grothendieck Feb 23 '17 at 18:08
  • 1
    Can you make an reproducible example? That would greatly improve the question and get you an answer. – John Paul Feb 23 '17 at 18:31
  • data.frame(A=,B=) works great, thanks! I'd like to use some of these others but they don't seem to work when I implement them. %T>% will let me make a plot as in the readme, but neither %T>% nor %>% will let me save any assignments I make inside the curly brackets, it's like they're just completely ignored. The readme says x %>% f(y,.) will ready as f(y,x), and it works for some functions, but x %>% assign("name", .) doesn't work for some reason. I have tidyverse, dplyr, and magrittr installed; is there another package so common as to be forgettable that I could be missing? – SenatorNyxen Feb 23 '17 at 18:47
  • arbitrary example: foo=c(1,2,3,4,5) %T>% {sum(.)->bar} %>% c(sqrt(.) ) I want it to append the list with its own square roots, and along the way I want it to also save the sum. When I run this code, nothing gets assigned to bar, whether I use %>%, %T>%, or assign("bar", value=.). Line 2 can fault if for instance I forget the quotes on bar, but otherwise it just ignored like it's not there. – SenatorNyxen Feb 23 '17 at 18:53
  • 1
    Yeah, I guess you would need to use `->>` or `<<-` instead. Though this may assign to the global env, which is not great, as MrFlick says below. – Frank Feb 23 '17 at 19:11

1 Answers1

2

You could write a function to do the assignment that you can include in the chain. Something like

save_to <- function(x, v) {
    var <- substitute(v)
    eval(bquote(.(var) <- .(x)), envir=globalenv())
    x
}


library(magrittr)
x<-1:10
f<-function(x) x+1
g<-function(x) x*2
h<-function(x) paste(x, collapse=", ")    

x %>% f %>% g %>% save_to(z) %>% h
# [1] "4, 6, 8, 10, 12, 14, 16, 18, 20, 22"
z
#  [1]  4  6  8 10 12 14 16 18 20 22

Note that this saves the value to the global environment. For this reason it's probably not a great idea (functions with side effects are generally a bad design practice in functional languages). It would be better to break it up into different chains.

z <- x %>% f %>% g
z %>% h
MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • 1
    Regarding the "different chains" way, this is also chainable: `res = {z <- x %>% f %>% g} %>% h` – Frank Feb 23 '17 at 19:14
  • Thanks all! Frank, that works great, but I don't understand why it's different from some of the very similar lines that don't. Is it just that there are pipes inside the brackets? – SenatorNyxen Feb 23 '17 at 20:38