21

I have a list of floats in R. For a given integer, N, I want to find the indices of the largest N values in my list. So for example, if N is 2, I want to find the indices of the two largest values in my list. How do I do this?

I cannot reorder my list. This is why I need the indices.

Steven C. Howell
  • 16,902
  • 15
  • 72
  • 97
user2560984
  • 361
  • 2
  • 6
  • 12

5 Answers5

28
order(R, decreasing=TRUE)[1:N]
Hong Ooi
  • 56,353
  • 13
  • 134
  • 187
6

Here is an alternative:

N <- 2
v <- c(3,  9, 11,  18,  5)
tail(order(v), N)
# [1] 3 4
QuantIbex
  • 2,324
  • 1
  • 15
  • 18
6

All of the other current answers require a call to order that will run in O(M log M) time. If N is much smaller than the total number of elements M, a quicker way is to partially sort the list and then to extract the indices greater than or equal to the N'th largest. This has O(M + N log N) running time and will be much quicker for large M.

v <- list(1,7,4,3,9,1,2,3,0,1,2)
vec <- unlist(v)
N <- 3
partial <- length(v) - N + 1
Nth <- sort(vec, partial = partial)[partial]
indexes <- which(vec >= Nth)
vec[indexes]

Note this will not deal with ties in the list. There is a longer discussion here.

It is idiomatic to store numeric data in a vector not a list. Hence the call to unlist above.

As a function, this can be implemented like so:

maxn <- function(x, n) {
  partial <- length(x) - n + 1
  x[x >= sort(x, partial = partial)[partial]]
}
Ken Williams
  • 22,756
  • 10
  • 85
  • 147
Epimetheus
  • 1,119
  • 1
  • 10
  • 19
  • Thanks for this answer, I've found this code very useful. I have adapted it slightly to account for ties (by just looking at the unique values of x), and to allow the user to select max/min [here](https://stackoverflow.com/a/74453566/10366237). I haven't implemented the code as efficiently as possible though, and I am sure it's asymptotic runtime is quite a bit higher than this initial code. – diomedesdata Nov 16 '22 at 04:23
4

You probably mean vector and not a list, and here's an example:

v = c(1,7,4,3,9)
v[order(-v)][1:3]
#[1] 9 7 4

Re comment:

order(-v)[1:3]
#[1] 5 2 3
eddi
  • 49,088
  • 6
  • 104
  • 155
0

I think this works as well:

x <- list(1, 2, 2, 4, 5, 5)
which(x %in% max(unlist(x)))
Stein Monteiro
  • 191
  • 2
  • 5