great video, thanks a lot. just one side note starting with R version 4.2, you can use the (_) as data placeholder like the (.) in the Magrittr. so the syntax would be: |> cor.test(~prcp+ snow, data = _)
Finally Pat started the nerd talk! I love it! I want to add I never wrote a single time in my life the pipe manually. For the others besides Pat's highly trained fingers: Just press cntrl+shift + m on Windows or cmd + shift + m on my mac.
Great video, Pat, Thanks a lot. I actually use the %T>% pipe inside functions quite often, for example, to plot and intermediate result or print a data.frame I do further work with.
Very clear presentation. I want to add a few things to give a fairer comparison to base R (irrespective of the pipe). Base R has na.omit() and subset() which are essentially the same as drop_na() and filter(), so you can run the first set of code just as cleanly in base R as follows: local_weather |> na.omit() |> subset(snow > 0) Similarly, base R has the transform() and within() functions, which work very similar to mutate(). As others have mentioned, we now have the _ placeholder for piping to arguments other than the first. Though it's also worth noting that |> pipes to the first *unnamed* argument. So no_na_no_zero |> cor.test(formula = ~prcp+snow) also works, because the first unnamed argument is data, which the dataset is then passed to. An alternative to %$% in base R is with(), e.g., no_na_no_zero |> with(cor.test(prcp, snow)). The first argument to with() is the dataset and the second is the expression you want to run, which makes it amenable to piping. Just wanted to add to the info you presented for those interested. I think base R gets a bad rap sometimes, but it's not always as obtuse as some make it out to be.
I'm a data scientist, and given the scale of data I work with, the difference in performance is a consideration for me. I won't deny that the dot notation for the standard Magrittr pipe is incredibly useful though. I'm pretty curious about the trade-off in performance between loading the magrittr pipe for base R functions like gsub versus using the Base R pipe for pipe-friendly functions from tidyverse packages like str_replace_all. I don't expect you to go into all that though. I can test it on my own. Also, huge thanks for the introduction to the other pipes and alias functions because I've been overlooking them, and they could come in super handy for more readable code. Great video!
if you are working on performance-critical applications, syntactic sugar like tidyverse could be an intermediate step to translate thoughts to code, then optimize afterward through dtplyr or translating to base R. Magrittr is part of the fastverse suit of packages, but has a minimal overhead (2 * substitute calls + environment juggling) whereas base R pipe relies on the parser, so transition between pipes should give a very minimal performance boost. A greater concern would be if your project needs such dependencies (and what happens if one dependency breaks)
Excellent video. Always forget that cor.test is available. Much easier to pipe in as opposed to the cumbersome dataframe %>% select(x,y) %>% cor(x, y). Also had no idea set_colnames existed. Was using a purr function for years. Similar, but one fewer argument which I always forgot. Thank you Dr. Pat.
Hi Pat. Thanks for the video. I haven't spent any time looking at the magrittr aliases and they do look useful for certain use cases. One comment though. When you mention show the base pipe workflow, you didn't use the `_` placeholder to replace the `.` from {magrittr}. I demonstrate the use of the placeholder below: ``` data("CO2") CO2 |> cor.test(~ conc + uptake, data = _) ``` The placeholder was added in R 4.2 (I think) and, as I understand it, the _ placeholder can only be used for a named argument - so not a positional argument, nor a ... argument. I still use the magrittr pipe by default for interactive workflows, but I think that the the R base pipe is a better fit when I work on packages. I also haven't found a use for the eager pipe and I also avoid the assignment pipe for the same reasons that you mention. If I want to produce a modified dataframe I will usually pipe the first assignment call: ``` my_data % drop_na() %>% filter(....) ``` This makes it obvious that my_data is not the raw data from the read_csv call, but doesn't give me eye-strain looking for %% hidden in my code. 🤣
I fell like in the base demonstration you could just as simple as the tidy way to write no_na_no_zero 0]) and it would be a lot simpler than the original code... Still of course its the tidy way or no way, but base R can also be readble
Thanks - again this is just meant to be one example of nesting base r functions. I think what you have written is a lot less readable than the piped version. The argument over pipes or not is really about readability.
Be sure to check out the follow up episode to this one!
ruclips.net/video/TmSwDAvPX2Q/видео.html
great video, thanks a lot. just one side note starting with R version 4.2, you can use the (_) as data placeholder like the (.) in the Magrittr.
so the syntax would be: |> cor.test(~prcp+ snow, data = _)
That’s great - thanks!
"ceci n'est pas une* pipe" is a thing of beauty. You should put it on a t-shirt!
I'd buy it in a heartbeat.
🤓that’s the magic of the magrittr developers very cool tool
Finally Pat started the nerd talk! I love it!
I want to add I never wrote a single time in my life the pipe manually.
For the others besides Pat's highly trained fingers:
Just press cntrl+shift + m on Windows or cmd + shift + m on my mac.
Lol - someday I’ll refrain my fingers 🤓
No wonder the output of line 10 is the same as line 7; they both use the same data 😁! Awesome video as usual.
Great video, Pat, Thanks a lot. I actually use the %T>% pipe inside functions quite often, for example, to plot and intermediate result or print a data.frame I do further work with.
Very cool. I’ll have to try using it more
Very clear presentation. I want to add a few things to give a fairer comparison to base R (irrespective of the pipe). Base R has na.omit() and subset() which are essentially the same as drop_na() and filter(), so you can run the first set of code just as cleanly in base R as follows:
local_weather |> na.omit() |> subset(snow > 0)
Similarly, base R has the transform() and within() functions, which work very similar to mutate().
As others have mentioned, we now have the _ placeholder for piping to arguments other than the first. Though it's also worth noting that |> pipes to the first *unnamed* argument. So no_na_no_zero |> cor.test(formula = ~prcp+snow) also works, because the first unnamed argument is data, which the dataset is then passed to. An alternative to %$% in base R is with(), e.g., no_na_no_zero |> with(cor.test(prcp, snow)). The first argument to with() is the dataset and the second is the expression you want to run, which makes it amenable to piping.
Just wanted to add to the info you presented for those interested. I think base R gets a bad rap sometimes, but it's not always as obtuse as some make it out to be.
Thanks for watching! I did a follow up episode where I covered much of this here:
ruclips.net/video/IL31LG84i5M/видео.html
I cant believe i'm here. I can just watch R videos and understand things enough to not need to pause and go back to learn something, then resume.
Ha! Wonderful Trevor 🤓
The video we didn't know we needed came the exact same time we needed!! Thanks for sharing. I love your content!
Thanks for watching! 🤓
I didn't know there were so many pipes. Thanks, very interesting!
I'm a data scientist, and given the scale of data I work with, the difference in performance is a consideration for me. I won't deny that the dot notation for the standard Magrittr pipe is incredibly useful though. I'm pretty curious about the trade-off in performance between loading the magrittr pipe for base R functions like gsub versus using the Base R pipe for pipe-friendly functions from tidyverse packages like str_replace_all. I don't expect you to go into all that though. I can test it on my own. Also, huge thanks for the introduction to the other pipes and alias functions because I've been overlooking them, and they could come in super handy for more readable code. Great video!
Thanks! 🤓
if you are working on performance-critical applications, syntactic sugar like tidyverse could be an intermediate step to translate thoughts to code, then optimize afterward through dtplyr or translating to base R. Magrittr is part of the fastverse suit of packages, but has a minimal overhead (2 * substitute calls + environment juggling) whereas base R pipe relies on the parser, so transition between pipes should give a very minimal performance boost. A greater concern would be if your project needs such dependencies (and what happens if one dependency breaks)
@@k1llyah Wow, this is genuinely fantastic and thoughtful advice. Thank you so much!
Thank you very much!!!! Super super informative.
Excellent video. Always forget that cor.test is available. Much easier to pipe in as opposed to the cumbersome dataframe %>% select(x,y) %>% cor(x, y). Also had no idea set_colnames existed. Was using a purr function for years. Similar, but one fewer argument which I always forgot. Thank you Dr. Pat.
Thanks Marc!
I love the Ctrl-Shift-m hot key for the Magritter pipe. My fingers hate reaching for that top row
Some day I’ll learn it too 😂
Wow. I never knew there were other pipes other than %>%. Thanks for the video.
My pleasure! Thanks for watching Timmy🤓
I agree that the %T>% pipe is not terribly useful but I do like it to look at both the head and the tail of a data frame in one pipe.
Agreed. Thanks for watching!
Hi Pat. Thanks for the video. I haven't spent any time looking at the magrittr aliases and they do look useful for certain use cases.
One comment though. When you mention show the base pipe workflow, you didn't use the `_` placeholder to replace the `.` from {magrittr}. I demonstrate the use of the placeholder below:
```
data("CO2")
CO2 |>
cor.test(~ conc + uptake, data = _)
```
The placeholder was added in R 4.2 (I think) and, as I understand it, the _ placeholder can only be used for a named argument - so not a positional argument, nor a ... argument.
I still use the magrittr pipe by default for interactive workflows, but I think that the the R base pipe is a better fit when I work on packages.
I also haven't found a use for the eager pipe and I also avoid the assignment pipe for the same reasons that you mention.
If I want to produce a modified dataframe I will usually pipe the first assignment call:
```
my_data %
drop_na() %>%
filter(....)
```
This makes it obvious that my_data is not the raw data from the read_csv call, but doesn't give me eye-strain looking for %% hidden in my code.
🤣
Thanks! 🤓
Tee Pipe is useful if you want to inject console progress messages while pipeline is executing.
Yup - I kinda mention this in the video
Fira Code font displays the native R pipe as an arrowhead which is super cool (but not the Magrittr pipe)
Thanks for the info!
God damn, thank you
My pleasure
"Ceci n'est pas une pipe" ("This is not a pipe")
- René Magritte
hence `magrittr::%>%`
0:58 Look, mama, I'm famous!
Ha! Thanks for the question 🤓
you did what I never accomplished for years :D
just use %>% 😃
🤓
you do know is that to direct the output of |> to an arbitrary arg w a function:
... |> \(x) cor.test(..., x)
I fell like in the base demonstration you could just as simple as the tidy way to write no_na_no_zero 0]) and it would be a lot simpler than the original code... Still of course its the tidy way or no way, but base R can also be readble
Thanks - again this is just meant to be one example of nesting base r functions. I think what you have written is a lot less readable than the piped version. The argument over pipes or not is really about readability.