3

I have seen answers to the question:
Is it possible to arrange a numpy array (or python list) by using the indexes of the elements in decreasing order? (eg. Finding the Index of N biggest elements in Python Array / List Efficiently)

A very concise answer seems to be (from above link):

L = array([4, 1, 0, 8, 5, 2])
sorted(range(len(L)), key=lambda i:L[i])

This gives the position (in the original array) of the sorted elements.

8 --> 3
5 --> 4
4 --> 0
2 --> 5
1 --> 1
0 --> 2

So the answer is:

[3, 4, 0, 5, 1, 2]

What I am after is the position (in the sorted array) of the elements:

L = array([4, 1, 0, 8, 5, 2])

8 --> 0
5 --> 1
4 --> 2
2 --> 3
1 --> 4
0 --> 5

So I want :

[2, 4, 5, 0, 1, 3] 

I realise I could take the answer from the first example, and use that to get what I want (with a bit more fiddling) but is there a short cut?

Efficiency is not a concern. I just need something that gives me the answer.

shx2
  • 61,779
  • 13
  • 130
  • 153
RustyC
  • 61
  • 1
  • 5
  • Thanks guys for your responses. I like the use of the lambda expression twice to get what I what. Now is someone can just explain (in really simple terms for a tyro) how that line of code actually operates I will be grateful! – RustyC Dec 18 '13 at 23:08

3 Answers3

3

EDIT when I first read the question, I thought you were looking for numpy.argsort.

Having read it again, I realized I misread.

scipy.stats.rankdata is what you're looking for (offset by 1, and reversed)

(scipy.stats.rankdata([4, 1, 0, 8, 5, 2])-1)[::-1]
=> array([ 2.,  4.,  5.,  0.,  1.,  3.])

(Original wrong answer, referring to argsort:)

from numpy import array, argsort
L = array([4, 1, 0, 8, 5, 2])
argsort(L)
=> array([2, 1, 5, 0, 4, 3])
shx2
  • 61,779
  • 13
  • 130
  • 153
0

You can simply use your technique twice to get the indices in the sorted list:

A=[4, 1, 0, 8, 5, 2]
B=sorted(range(len(A)),key=lambda x:A[x],reverse=True)
C=sorted(range(len(A)),key=lambda x:B[x])
print C

prints

[2, 4, 5, 0, 1, 3]

Explanation

The idea is that the first iteration produces a list:

B = [3, 4, 0, 5, 1, 2]

giving the locations in the original list of the sorted sequence.

In other words, A[3]=8 is the largest element in the original list, A[4]=5 is the next largest, etc.

The second stage then sorts these indices in B back into the order 0,1,2,3,4,5 and produces C which contains the index in the list B.

It may help to think of B as sorting the list into descending order, and C as reversing the sort back into the original unsorted order, while keeping track of the indices in the sorted list.

Peter de Rivaz
  • 33,126
  • 4
  • 46
  • 75
-1

are you using numpy? if so, use numpy.argsort

import numpy as np
fakedata = np.array([40,20,60,50,10,20,80,30,50,40])
sorted_index = np.argsort(fakedata)
print(sorted_index)
print(fakedata[sorted_index])
[4 1 5 7 0 9 3 8 2 6] # sorted index
[10 20 20 30 40 40 50 50 60 80] # values selected by the sorted index
Paul H
  • 65,268
  • 20
  • 159
  • 136
  • 3
    This is an answer to the first part of my question - the one that has already been answered elsewhere. I want: _For each element in the original list give me its position in the sorted list_. Not: _For each element in the sorted list give me its position in the original list._ – RustyC Dec 18 '13 at 22:59