...
Code Block |
---|
library(bench)
library(data.table)
library(tidyverse)
df_df <- data.frame(x = rnorm(10^5))
df_tbl <- as_tibble(df_df)
df_dt <- as.data.table(df_df)
r_pipe <- function(df) {
df ->.;
.[x < 0, ] ->.;
`+`(., 100)
}
dplyr_pipe <- function(df) {
df %>%
filter(x < 0) %>%
mutate(x = x + 100)
}
dt_pipe <- function(df) {
df[x < 0, ][
x + 100]
}
mark(base = r_pipe(df_df),
dplyr = dplyr_pipe(df_tbl),
data.table = dt_pipe(df_dt),
iterations = 1000,
check = FALSE) %>%
arrange(median) %>%
select(-result:-gc)
# A tibble: 3 x 9
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time
<bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm>
1 base 595.2us 651.1us 1498. 1013.08KB 0 1000 0 667.45ms
2 dplyr 1.36ms 1.66ms 562. 2.32MB 0.562 999 1 1.78s
3 data.table 4.32ms 5.59ms 163. 2.53MB 1.81 989 11 6.08s |
Goofing around a bit more with R’s native “pipe”. Note that this is just for fun and using this syntax is strongly discouraged as it is difficult to understand. That said, a base R pipe, akin to the {magrittr}
pipe is coming.
Code Block |
---|
|
#Using R's native pipe operator
#Inspiration:
#https://win-vector.com/2017/07/07/in-praise-of-syntactic-sugar/
#The native pipe: `->.;`
#Basic example, using the typical assignment direction.
# Note the need to create a child environment with `{}` to get this to work.
# Also note the need to explicitly use dot notation to signify a resulting
# object.
result_v1 <- {
0 ->.; #The native "pipe"
cos(.)
}
result_v1
#> [1] 1
#Another example without a child environment, but requires assignment at the
# bottom of the code.
0 ->.;
cos(.) -> result_1_v2
result_v2
#> Error in eval(expr, envir, enclos): object 'result_v2' not found
#This example expands the use of the pipe to include an infix operator as a
# function, making operators like `+`, `-`, `*` pipe friendly.
result_3a <- {
0 ->.;
cos(.) ->.;
`+`(., 2 * .) #Infix operator
}
result_3a
#> [1] 3
#Here we have pipes inside of pipes with the "dot" having different meanings,
# depending on where it is used. This is because each environment can have its
# own definition of what an object means. Useful when piped operations are
# complex, or you are using lambda/anonymous functions that recycle variable
# names.
result_3b <- {
0 ->.;
cos(.) ->.;
`+`(., { #Child environment inside another environment
. ->.;
`*`(., 2)
}
)
}
result_3b
#> [1] 3
#Same as above, just proving to myself that the result is behaving as expected.
result_4 <- {
0 ->.; #The native "pipe"
cos(.) ->.;
`+`(., {
. ->.; #Infix operator
`*`(., 3)
}
)
}
result_4
#> [1] 4 |