Home > database >  dplyr arrange data frame based on column position with new R pipe |>
dplyr arrange data frame based on column position with new R pipe |>

Time:03-02

I want to sort my data frame based on a column that I pass to dplyr's arrange function with its position. This works as long as I'm using the "old" tidyverse/magrittr pipe operator. However, changing it to the new R pipe returns an error:

df <- data.frame(x = c(3, 4, 1, 5),
                 y = 1:4)

# Works
df %>% 
  arrange(.[1])

  x y
1 1 3
2 3 1
3 4 2
4 5 4

# Throws error
df |> 
  arrange(.[1])

Error:
! arrange() failed at implicit mutate() step. 
Problem with `mutate()` column `..1`.
i `..1 = .[1]`.
x object '.' not found
Run `rlang::last_error()` to see where the error occurred.

How can I still arrange by column position when using the new R pipe?

I realize that the |> operator does not accept the "." as an argument, but I still don't know how else I could address the data then.

Update:

This seems to work, but wondering if there is something more straightforward:

df |> 
  arrange(cur_data() |> select(1))

CodePudding user response:

You can pass a lambda function (suggestion by @Martin Morgan in the comments to specify the columns position instead of names):

df <- data.frame(x = c(3, 4, 1, 5),
                 y = 1:4)

df |> 
  (\(z) arrange(z, z[[1]]))()

#   x y
# 1 1 3
# 2 3 1
# 3 4 2
# 4 5 4

With order, this looks okay:

df |>
  (\(z) z[order(z[,1]), ])()

  x y
3 1 3
1 3 1
2 4 2
4 5 4

CodePudding user response:

|> does not support dot but tidyverse functions do support cur_data().

# 1
df |> arrange(cur_data()[1])

Another possibility is the Bizarro pipe which is not really a pipe but does look like one and uses only base R.

# 2
df ->.; arrange(., .[1])

or any of these work-arounds

# 3
arrange1 <- function(.) arrange(., .[1])
df |> arrange1()

# 4
df |> (function(.) arrange(., .[1]))()

# 5
df |> list() |> setNames(".") |> with(arrange(., .[1]))

# 6
with. <- function(data, expr, ...) {
  eval(substitute(expr), list(. = data), enclos = parent.frame())
}    
df |> with.(arrange(., .[1]))

# these hard code variable names so are not directly comparable
# but can be used if that is ok

# 7
df |> arrange(x)

# 8
df |> with(arrange(data.frame(x, y), x))
  • Related