order()
order(..., na.last = TRUE, decreasing = FALSE) order() returns the indices that would sort a vector or set of vectors. Unlike sort() which returns the sorted values, order() returns the positions that would reorder the data. This makes it essential for sorting data frames by one or multiple columns.
Syntax
order(..., na.last = TRUE, decreasing = FALSE)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
... | vectors | , | One or more vectors to order by. Multiple vectors create hierarchical sorting. |
na.last | logical | TRUE | How to handle NA values: TRUE puts them at the end, FALSE at the beginning, NA removes them., |
decreasing | logical | FALSE | If TRUE, sort in descending order. |
Examples
Basic usage
# Sort a numeric vector
x <- c(3, 1, 4, 1, 5, 9, 2, 6)
order(x)
# [1] 2 4 7 1 3 5 8 6
# Use the indices to reorder
x[order(x)]
# [1] 1 1 2 3 4 5 6 9
# Sort in descending order
x[order(x, decreasing = TRUE)]
# [1] 9 6 5 4 3 2 1 1
The basic call shows order() returning integer positions, not sorted values. This indirection is what gives order() its real utility — you can apply the same permutation to a data frame or to a parallel variable. For instance, y[order(x)] reorders y to match the sorted order of x, which is something sort() cannot do directly.
Sorting a data frame by multiple columns
df <- data.frame(
name = c("Alice", "Bob", "Carol", "David", "Eve"),
score = c(85, 92, 78, 92, 88),
age = c(25, 30, 25, 30, 28)
)
# Sort by score (descending), then by age (ascending)
df[order(df$score, df$age, decreasing = c(TRUE, FALSE)), ]
# name score age
# 2 Bob 92 30
# 4 David 92 30
# 5 Eve 88 28
# 1 Alice 85 25
# 3 Carol 78 25
Sorting by multiple columns with order() is the base R equivalent of dplyr::arrange(). The key difference is that order() returns positions you must use to subscript the data frame, while arrange() handles the reordering internally. For simple use cases, the base R approach is concise and has no external dependencies.
Handling NA values
y <- c(2, NA, 1, 4, NA, 3)
# Default: NAs at the end
order(y)
# [1] 3 6 1 4 2 5
# NAs at the beginning
order(y, na.last = FALSE)
# [1] 2 5 3 6 1 4
# Remove NAs entirely
order(y, na.last = NA)
# [1] 3 6 1 4
Common patterns
Using with dplyr: While dplyr::arrange() is more readable, order() is useful when you need the actual indices for complex operations. The pattern order(x, decreasing = TRUE)[1:3] extracts the indices of the top 3 values, and passing those indices back to the original vector gives the values themselves — a two-step lookup that is not directly expressible with sort() alone.
# Find the top 3 values and their positions
x <- c(10, 45, 12, 67, 23, 89, 5)
idx <- order(x, decreasing = TRUE)[1:3]
x[idx]
# [1] 89 67 45
Stable sorting: order() in R is stable, meaning elements with equal keys maintain their relative order.
order() in practice
order() returns the permutation of indices that would sort the vector: x[order(x)] produces a sorted x. This indirection is order()’s key property, it lets you sort one vector using the ordering determined by another. df[order(df$col), ] sorts a data frame by a column, which is the base R equivalent of dplyr::arrange().
For descending order, use order(x, decreasing = TRUE) or negate numeric values: order(-x). To sort by multiple columns with independent direction controls, pass multiple arguments: order(df$col1, -df$col2) sorts by col1 ascending, then by -col2 ascending (which is col2 descending). Negation only works for numeric columns; for character columns, use xtfrm(): order(xtfrm(df$char_col), decreasing = TRUE).
order() is stable: elements that compare equal retain their original relative order. This matches sort() behavior with method = "shell" (the default). For large vectors, order() uses an algorithm optimized for the data type, radix sort for integers and doubles by default since R 3.3, which is substantially faster than the earlier comparison-based sort.
The na.last argument controls where NA values sort: NA last (the default for order()), NA first, or NA excluded. order(x, na.last = NA) returns only indices of non-missing values, effectively excluding NA from the sort.
order() returns the permutation that would sort the input, the integer positions of elements in sorted order. x[order(x)] is equivalent to sort(x). For data frame sorting, df[order(df$col), ] is the base R equivalent of dplyr::arrange(). Pass multiple arguments for multi-key sorting: order(df$a, df$b) sorts by a first, then b within ties.
order() returns the permutation that would sort the input — the integer positions of elements in sorted order. x[order(x)] is equivalent to sort(x). The key advantage of order() over sort() is that you can apply the same permutation to related data: y[order(x)] reorders y to match the sorted order of x.
For multi-key sorting, pass multiple arguments: order(a, b) sorts by a ascending, breaking ties by b ascending. Wrap with decreasing = TRUE or pass a vector of booleans to decreasing for mixed ascending/descending sort. In dplyr, arrange(df, a, desc(b)) is equivalent.
order() with na.last = NA excludes NA positions from the permutation. na.last = TRUE (default) places NA values at the end; na.last = FALSE places them at the front.
rank() is related but returns ranks (1 to n) rather than positions. order(order(x)) computes the ranks, equivalent to rank(x, ties.method = "first").