'%>% .$column_name equivalent for R base pipe |>

I frequently use the dplyr piping to get a column from a tibble into a vector as below

iris %>% .$Sepal.Length
iris %>% .$Sepal.Length %>% cut(5)

How can I do the same using the latest R built-in pipe symbol |>

iris |> .$Sepal.Length
iris |> .$Sepal.Length |>  cut(5)
Error: function '$' not supported in RHS call of a pipe


Solution 1:[1]

We can use getElement().

iris |> getElement('Sepal.Length') |> cut(5)

Solution 2:[2]

In base pipe no placeholder is provided for the data that is passed in the pipe. This is one difference between magrittr pipe and base R pipe. You may use an anonymous function to access the object.

iris |> {\(x) x$Sepal.Length}()

Solution 3:[3]

The direct usage of $ in |> is currently disabled. If the call of $ or other disabled functions in |> is still needed, an option, beside the creation of a function is to use $ via the function :: as base::`$` or place it in brakes ($):

iris |> (`$`)("Sepal.Length")

iris |> base::`$`("Sepal.Length")

iris |> (\(.) .$Sepal.Length)()

fun <- `$`
iris |> fun(Sepal.Length)

This will also work in cases where more than one column will be extracted.

iris |> (`[`)(c("Sepal.Length", "Petal.Length"))

Another option can be the use of a bizarro pipe ->.;. Some call it a joke others clever use of existing syntax.

iris ->.; .$Sepal.Length

This creates or overwrites . in the .GlobalEnv. rm(.) can be used to remove it. Alternatively it could be processed in local:

local({iris ->.; .$Sepal.Length})

In this case it produces two same objects in the environment iris and . but as long as they are not modified they point the the same address.

tracemem(iris)
#[1] "<0x556871bab148>"
tracemem(.)
#[1] "<0x556871bab148>"

|> is used as a pipe operator in R.

The left-hand side expression lhs is inserted as the first free argument in the call of to the right-hand side expression rhs.

mtcars |> head()                      # same as head(mtcars)
#                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
#Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

mtcars |> head(2)                     # same as head(mtcars, 2)
#              mpg cyl disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4      21   6  160 110  3.9 2.620 16.46  0  1    4    4
#Mazda RX4 Wag  21   6  160 110  3.9 2.875 17.02  0  1    4    4

It is also possible to use a named argument with the placeholder _ in the rhs call to specify where the lhs is to be inserted. The placeholder can only appear once on the rhs.

mtcars |> lm(mpg ~ disp, data = _)
#mtcars |> lm(mpg ~ disp, _)  #Error: pipe placeholder can only be used as a named argument
#Call:
#lm(formula = mpg ~ disp, data = mtcars)
#
#Coefficients:
#(Intercept)         disp  
#   29.59985     -0.04122  

Alternatively explicitly name the argument(s) before the "one":

mtcars |> lm(formula = mpg ~ disp)

In case the placeholder is used more than once or used as a named or also unnamed argument on any position or for disabled functions: Use an (anonymous) function.

mtcars |> (\(.) .[.$cyl == 6,])()
#mtcars ->.; .[.$cyl == 6,]           # Alternative using bizarro pipe
#local(mtcars ->.; .[.$cyl == 6,])    # Without overwriting and keeping .
#                mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#Merc 280       19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#Merc 280C      17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#Ferrari Dino   19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6

mtcars |> (\(.) lm(mpg ~ disp, .))()
#Call:
#lm(formula = mpg ~ disp, data = .)
#
#Coefficients:
#(Intercept)         disp  
#   29.59985     -0.04122  

An expression written as x |> f(y) is parsed as f(x, y). While the code in a pipeline is written sequentially, regular R semantics for evaluation apply. So piped expressions will be evaluated only when first used in the rhs expression.

Solution 4:[4]

Interesting example and great answers, let me add another version: I use usually selectand then unlist in such cases. This follows the "speaking R" paradigm and works same with both operators %>% and |>:

library("dplyr")
iris %>% select(Sepal.Length) %>% unlist() %>% cut(5)

iris |> select(Sepal.Length) |> unlist() |> cut(5)

Note that select is from dplyr and pull brought in from @jpdugo17 is even better.

If we use usual "base R" indexing, it is also short and works in both worlds:

iris[["Sepal.Length"]] |> cut(5)

iris$Sepal.Length |> cut(5)

and thanks to the comment of @zx8754 one can of course also use base R without any pipes

cut(iris$Sepal.Length, 5)

... but I think that the OP just wanted to point out differences in piping. I guess that it is to be applied in a bigger context and iris is only an example.

Solution 5:[5]

This is also an option:

iris |> dplyr::pull(Sepal.Length) |> cut(5)

Edit:

I wonder why calling a function with backticks isn't allowed.

iris |> `[`(, 'Sepal.Length')
#>Error: function '[' not supported in RHS call of a pipe 

As pointed out by @Hugh, backticks are allowed but some functions are not.

Here's the blacklisted functions list extracted from wch Github

"if", "while", "repeat", "for", "break", "next", "return", "function",
"(", "{",
"+", "-", "*", "/", "^", "%%", "%/%", "%*%", ":", "::", ":::", "?", "|>",
"~", "@", "=>",
"==", "!=", "<", ">", "<=", ">=",
"&", "|", "&&", "||", "!",
"<-", "<<-", "=",
"$", "[", "[[",
"$<-", "[<-", "[[<-",
0

Solution 6:[6]

I know this question is closed. Other Base R solutions where we use symbol name instead of the character name might include:

 iris |>
    with(Sepal.Length)


 iris |>
    subset(select = Sepal.Length)

Solution 7:[7]

Since R 4.2.0, you can use _ as a placeholder for |>. Because "functions in rhs calls [can] not be syntactically special", you cannot use $ directly, so you have to define the function with another name first, and then use the placeholder and the column name:

set <- `$`
iris |> set(x = _, Sepal.Length)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jay.sf
Solution 2 Ronak Shah
Solution 3
Solution 4
Solution 5
Solution 6 onyambu
Solution 7