How to order rows in dataframe with a new piping in r?

Viewed 51

I want to use a new R pipe |> for the script like this:

df <- data.frame (letter=c(rep("a",3), rep("b",3), rep("c",2)),
                    number = c(1,3,4,7,6,2,5,8))
df <- df[which(df$letter !="c"),]
df <- df[order(df$number),]

I tried this

df <- data.frame (letter=c(rep("a",3), rep("b",3), rep("c",2)),
                  number = c(1,3,4,7,6,2,5,8)) |>
  df[which(df$letter !="c"),] |>
  df[order(df$number),]

But got an error

Error: function '[' not supported in RHS call of a pipe

How to use |> in this case to filter and order rows in a dataframe?

3 Answers

Here is an alternative suggestion. Not directly related to the provided code:

library(dplyr)

df |> 
  filter(letter != "c") |>
  arrange(number)

  letter number
1      a      1
6      b      2
2      a      3
3      a      4
5      b      6
4      b      7

You can use [ as a function then apply |> operator as follows

df <- df |> (\(x)`[`(x,which(df$letter !="c") ,))()

df |> (\(x)`[`(x,order(df$number) ,))()

  • output
  letter number
1      a      1
6      b      2
2      a      3
3      a      4
5      b      6
4      b      7

Another approach is to write a pipeable function to use instead of [ that would work in most instances, instead of case-by-case. A first try is DF <- function(x, ...) x[...] but this isn't great because you still need df$ inside the brackets and that refers to the original data.frame, not the piped one. So,

DF <- function(x, ...) eval(substitute(x[...]), envir = x)
df |> 
  DF(letter != "c", ) |> 
  DF(order(number), )

This allows dropping the df$ and doing a true pipe. The result is:

  letter number
1      a      1
6      b      2
2      a      3
3      a      4
5      b      6
4      b      7

(This idea came from what the dev version of the data.table package is doing with the DT() function.)

Also, subset(letter != "c") works just fine for the first part, then you don't need the extra comma.

Related