问题
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) %>%
?
回答1:
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
来源:https://stackoverflow.com/questions/42422215/r-pipe-capabilities-storage-and-partial-use