dplyr::relocate

relocate(.data, ..., .before = NULL, .after = NULL)
Returns: tibble · Updated April 5, 2026 · Tidyverse
dplyr r tidyverse data-wrangling

relocate() changes the positions of columns in a data frame without changing their values. It uses tidy-select syntax, which means you can move columns by name, by type, or using any of the familiar helper functions like starts_with() or where(). The difference from select() is that relocate() doesn’t drop columns — it only changes their order.

Signature

relocate(.data, ..., .before = NULL, .after = NULL)

Parameters

.data

A data frame, tibble, or lazy data frame from dbplyr or dtplyr.

— one or more columns to move. You can name them directly, use tidyselect helpers, or rename on the fly with new_name = old_name.

.before

Move the selected columns immediately before this column (or columns). Accepts a tidy-select expression.

.after

Move the selected columns immediately after this column (or columns). Accepts a tidy-select expression.

Return Value

A tibble with the same rows, columns, and attributes as the input, with only the column order changed. Groups are preserved.

Basic Usage

library(dplyr)

df <- tibble(a = 1, b = 1, c = 1, d = "a", e = "a", f = "a")

# Move column f to the leftmost position
df |> relocate(f)
#> # A tibble: 1 × 6
#>   f     a     b     c     d     e
#>   <chr> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 a     1     1     1     a     a

When you supply neither .before nor .after, the selected columns move to the leftmost position.

Moving Relative to Another Column

Use .after to place moved columns after a specific column:

df |> relocate(a, .after = c)
#> # A tibble: 1 × 6
#>   b     c     a     d     e     f
#>   <dbl> <dbl> <dbl> <chr> <chr> <chr>
#> 1 1     1     1     a     a     a

Use .before to place them before a specific column:

df |> relocate(f, .before = b)
#> # A tibble: 1 × 6
#>   a     f     b     c     d     e
#>   <dbl> <chr> <dbl> <dbl> <chr> <chr>
#> 1 1     a     1     1     a     a

You can only use one of .before or .after at a time — using both is an error.

Using last_col()

Move a column to the rightmost position using last_col():

df |> relocate(a, .after = last_col())
#> # A tibble: 1 × 6
#>   b     c     d     e     f     a
#>   <dbl> <dbl> <chr> <chr> <chr> <dbl>
#> 1 1     1     a     a     a     1

Renaming During a Move

Like rename(), relocate() accepts new_name = old_name syntax so you can move and rename in one step:

df |> relocate(ff = f)
#> # A tibble: 1 × 6
#>   ff    a     b     c     d     e
#>   <chr> <dbl> <dbl> <dbl> <chr> <chr>
#> 1 a     1     1     1     a     a

Moving by Type

Because relocate() uses tidy-select, you can move all columns of a certain type at once:

# Move all character columns to the front
df |> relocate(where(is.character))
#> # A tibble: 1 × 6
#>   d     e     f     a     b     c
#>   <chr> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 a     a     a     1     1     1

# Move all numeric columns to the end
df |> relocate(where(is.numeric), .after = last_col())
#> # A tibble: 1 × 6
#>   d     e     f     a     b     c
#>   <chr> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 a     a     a     1     1     1

Moving Multiple Columns to a Multiple-Column Destination

When .before or .after references multiple columns, the moved columns slot in adjacent to all of them:

df2 <- tibble(a = 1, b = "a", c = 1, d = "a")

# Move numeric columns after all character columns
df2 |> relocate(where(is.numeric), .after = where(is.character))
#> # A tibble: 1 × 4
#>   b     d     a     c
#>   <chr> <chr> <dbl> <dbl>
#> 1 a     a     1     1

# Move character columns before all numeric columns
df2 |> relocate(where(is.character), .before = where(is.numeric))
#> # A tibble: 1 × 4
#>   a     c     b     d
#>   <dbl> <dbl> <chr> <chr>
#> 1 1     1     a     a

Using any_of() and Other Helpers

df |> relocate(any_of(c("a", "e", "i", "o", "u")))
#> # A tibble: 1 × 6
#>   a     e     b     c     d     f
#>   <dbl> <chr> <dbl> <dbl> <chr> <chr>
#> 1 1     a     1     1     a     a

any_of() is useful when you’re not sure whether all the columns exist — it silently ignores missing ones.

relocate() vs select()

Both can reorder columns, but they differ in intent:

relocate()select()
Drops other columnsNoYes (unless you include everything())
Rename during reorderYesYes
Move by typeYes (via tidy-select)Yes
Best forMinor reorderingSelecting a subset + reordering

In practice, relocate() is cleaner when you want to adjust column order without thinking about every other column. select() is better when you’re explicitly choosing which columns to keep.

See Also