0

The function order in R returns a permutation which rearranges its first argument into ascending or descending order, breaking ties by further arguments. What I want is the permutation without tie breaks

set.seed(1)
b <- sample(round(rnorm(3),2),9,replace=TRUE)
b
#>[1] [1] -0.84  0.18  0.18 -0.63 -0.63 -0.63 -0.84  0.18 -0.84
# should be
[1] 1 3 3 2 2 2 1 3 1

1 Answers1

3

You can use match

match(b, sort(unique(b)))
# [1] 1 3 3 2 2 2 1 3 1

As mentioned by Jesper in the comments another option is

as.integer(factor(b))

Gregor mentioned dense_rank from dplyr

dplyr::dense_rank(b)

and frank from data.table

data.table::frank(b, ties.method = "dense")

but match is most efficient given below sample data

set.seed(1)
b <- sample(round(rnorm(3), 2), 100000, replace = TRUE)

benchmark <- microbenchmark(
  match = match(b, sort(unique(b))),
  factor = as.integer(factor(b)),
  dplyr = dplyr::dense_rank(b),
  data.table = data.table::frank(b, ties.method = "dense")
)

autoplot(benchmark)

enter image description here

benchmark
#Unit: milliseconds
#       expr       min         lq       mean     median         uq       max neval  cld
#      match  3.860337   3.992396   4.507669   4.408813   4.712448   7.77195   100 a   
#     factor 98.624234 100.011022 106.285972 103.896008 108.603783 147.02728   100    d
#      dplyr 22.824663  23.388366  25.112084  24.062046  25.720228  39.88105   100   c 
# data.table  6.370802   6.563733   8.854151   6.773746   7.476541  51.12899   100  b  
markus
  • 25,843
  • 5
  • 39
  • 58