4

I have a vector that looks something like this:

> vec
[1]  1  1  2  5 10

I'm trying to convert this to a form of non-olympic ranking where ties are still ties, but the ranks are guaranteed 1 apart, even when there are multiple ties above it, so:

> f(vec)
[1]  1  1  2  3  4

Rather than:

> rank(vec,ties.method="min")
[1] 1 1 3 4 5

Is there function that does this already in R? I know I could convert the values to factors then rank the factors, but that seems a bit circuitous. (If not a function, is there a name for this kind of ranking?)

(Fun: I hadn't noticed this before, but it looks like rank is idempotent, which is kinda cool:

> rank(vec,ties.method="min")
[1] 1 1 3 4 5
> rank(rank(vec,ties.method="min"),ties.method="min")
[1] 1 1 3 4 5

)

Mittenchops
  • 18,633
  • 33
  • 128
  • 246
  • Hmm, I guess this is called "Dense Ranking" https://en.wikipedia.org/wiki/Ranking#Dense_ranking_.28.221223.22_ranking.29 – Mittenchops Mar 13 '14 at 04:48

1 Answers1

8

Try this:

vec <- c(1,1,2,5,10)
> as.integer(factor(vec))
[1] 1 1 2 3 4

I realize now you mentioned the factor route. Personally I don't find it terribly offensive.

Or you could reach in the code of factor itself and do something mostly equivalent:

match(vec,unique(vec))

but that assumes that vec is sorted, so maybe you'd really have to do something like

match(vec,sort(unique(vec)))
joran
  • 169,992
  • 32
  • 429
  • 468