position
R has no single function called position(). Instead, several related functions handle positional indexing: which.max(), which.min(), rank(), and order(). This article covers them together, since they’re often used in combination to answer “where is the max?”, “what’s the rank order?”, and “what indices would sort this?“
which.max — Position of the Maximum
which.max returns the index of the first maximum value in a vector:
which.max(c(1, 3, 2, 3, 0))
# [1] 2
With ties, it returns the position of the first occurrence:
which.max(c(1, 3, 3, 3, 2))
# [1] 2 (first 3 is at position 2)
which.min is the equivalent for the minimum:
which.min(c(5, 1, 3))
# [1] 2
Both functions ignore NA and NaN values by default:
which.max(c(1, NA, 3, 2))
# [1] 3
To handle NAs explicitly, prefilter:
x <- c(1, NA, 3, 2)
which.max(x[!is.na(x)])
# [1] 3
which.max(na.omit(x))
# [1] 3
rank — Rank Values in a Vector
rank assigns ranks to values. The default tie method is "average":
rank(c(3, 1, 2))
# [1] 3 1 2
With ties, "average" assigns the mean rank:
rank(c(1, 2, 2, 3))
# [1] 1.0 2.5 2.5 4.0
Other tie methods handle ties differently:
rank(c(1, 2, 2, 3), ties.method = "first")
# [1] 1 2 3 4
rank(c(1, 2, 2, 3), ties.method = "min")
# [1] 1 2 2 4
rank(c(1, 2, 2, 3), ties.method = "max")
# [1] 1 3 3 4
na.last controls where NA values land:
rank(c(1, NA, 2), na.last = TRUE)
# [1] 1 NA 2 -- NA gets a rank
rank(c(1, NA, 2), na.last = FALSE)
# [1] NA 1 2 -- NA comes first
rank(c(1, NA, 2), na.last = NA)
# [1] 1 2 -- NA is removed
order — Indices for Sorting
order returns indices that would sort a vector:
order(c(3, 1, 2))
# [1] 2 3 1
# element at position 2 (value 1) comes first
# element at position 3 (value 2) comes second
# element at position 1 (value 3) comes third
Use these indices to reorder another vector:
x <- c("c", "a", "b")
x[order(c(3, 1, 2))]
# [1] "a" "b" "c"
For descending order:
order(c(3, 1, 2), decreasing = TRUE)
# [1] 1 3 2
Sort data frames by passing column arguments:
df <- data.frame(name = c("bob", "alice", "carol"), score = c(85, 92, 78))
df[order(df$score), ]
# name score
# 3 carol 78
# 1 bob 85
# 2 alice 92
Getting the Position of a Specific Value
To find positions matching a condition, use which():
x <- c(10, 20, 30, 40, 50)
which(x == 30)
# [1] 3
which(x > 25)
# [1] 3 4 5
For the first occurrence of a match, use match():
match(30, c(10, 20, 30, 40, 50))
# [1] 3
# Check existence of values:
30 %in% c(10, 20, 30, 40, 50)
# [1] TRUE
xtfrm — Auxiliary Sorting
xtfrm() produces a numeric vector that sorts in the same order as the input. It’s used internally by sort() and order() for non-numeric objects:
xtfrm(c("b", "a", "c"))
# [1] 2 1 3 (a=1, b=2, c=3)
# Useful for custom orderings:
xtfrm(factor(c("low", "high", "medium"),
levels = c("low", "medium", "high")))
# [1] 1 3 2
Relationship Between These Functions
| Function | Returns | Example input | Example output |
|---|---|---|---|
which.max(x) | index of first max | c(3,1,2) | 1 |
which.min(x) | index of first min | c(3,1,2) | 2 |
rank(x) | rank of each element | c(3,1,2) | 3, 1, 2 |
order(x) | indices for sorting | c(3,1,2) | 2, 3, 1 |
match(val, x) | index of first match | 30, c(10,20,30) | 3 |
Common Patterns
Find the Maximum Value (Not Just Its Position)
x <- c(3, 1, 4, 1, 5, 9)
x[which.max(x)]
# [1] 9
Get Top N Indices
order(x, decreasing = TRUE)[1:3]
# indices of the 3 largest values
Rank in Descending Order
rank(-x)
Common Pitfalls
Forgetting That which.max Returns an Index, Not the Value
which.max(x) # index
x[which.max(x)] # the actual value
Ties Give Unexpected Results With which.max
which.max(c(1, 2, 2, 2))
# [1] 2 -- only first occurrence
# Get ALL positions of max:
which(x == max(x))
# [1] 2 3 4
See Also
- /reference/base-functions/which/ — return indices of TRUE values
- /reference/base-functions/match/ — find positions of first matches between vectors
- /reference/base-functions/which-max/ — position of maximum/minimum value
- /reference/base-functions/find-base/ — locate objects in the search path by name