kezz_smc
kezz_smc

Reputation: 115

Sort by absolute value

Does anyone know how to sort a vector in R by absolute value, so (-2, 3, 1) -> (1, -2, 3) etc?

If I were doing it in python I'd create a pair of every value and its sign, sort the list of pairs by the absolute value then reapply the sign, but I'm very new to R so have no idea how to do this.

Cheers

Upvotes: 8

Views: 12005

Answers (2)

sds
sds

Reputation: 60014

@Arun's method is TRT:

v[order(abs(v))]

where v is the vector to be sorted.

Notes:

  • This creates a new vector abs(v) of the same size as v. This is not very memory-efficient, but I don't think this can be avoided in R, like it is done in, e.g., Lisp: (sort #'< v :key #'abs) or Python: v.sort(key=abs).
  • This temp vector allocation is not necessarily a bad thing: you do lose memory, but you win time because the accessor key is called only N times, not N*log(N) times, which is especially important when the key is not cheap (unlike abs or a structure field).
  • To be more precise, the vector abs(v) is garbage collected very soon, but its allocation (and, especially, garbage collection) are expensive for large vectors and may be actually problematic if the memory is tight.

See also:

Upvotes: 11

Jeromy Anglim
Jeromy Anglim

Reputation: 34907

I found it useful to package this in a function so that I could pass a vector to it, and also so that there was the option of using other options in the order function like decreasing. It is essentially based on the existing answer.

sort_abs <- function(x, na.last = TRUE, decreasing = FALSE) {
    x[order(abs(x), na.last = na.last, decreasing = decreasing)] 
}

For example,

> sort_abs(c(-1,NA,2,-2))
[1] -1  2 -2 NA
> sort_abs(c(-1,NA,2,-2), decreasing = TRUE, na.last = FALSE)
[1] NA  2 -2 -1

Upvotes: 2

Related Questions