Assign rank to numbers in a vector

2019-04-06 05:59发布

问题:

I want to be able to assign a rank to numbers in a vector depending on their size and make a new vector containing these ranks.

For instance, if I have the vector [5, 2, 3, 1], I want to return [4, 2, 3, 1] (as 5 is the largest number and 1 is the smallest). Equal numbers should share an average rank preferably (for instance, if both are the same and are the lowest, they should get an average rank of 1.5).

How can I achieve this in MATLAB?

回答1:

Instead of sorting, I suggest you use unique:

[~, ~, ranking] = unique(x);

It also sorts the vector but maps identical values to the same index. This way identical elements in the original vector get the same rank. For instance, if x = [5 2 3 1 3], we get:

ranking =
   4   2   3   1   3

If you want an "average" rank, you could use accumarray in combination with the information obtained both from unique and from sort, so do the following instead:

[~, ~, idx_u] = unique(x);
[~, idx_s] = sort(x);
mean_ranks = accumarray(idx_u(:), idx_s(idx_s), [], @mean);
ranking = mean_ranks(idx_u);

In our example we would get:

ranking =
   1.0000
   2.0000
   3.5000
   5.0000
   3.5000

Note that both values 3 got the average rank of 3.5, as they shared ranks 3 and 4.



回答2:

You can use the second output param of sort() to do what you want.

e.g. (tested in Matlab 2011b)

>> [~,ranking] = sort([5 2 3 1]);
>> ranking
ranking =
     4     2     3     1

EDIT: (The OP asked for further explanation)

From your example, I determined that higher ranks go to larger numbers, so it's essentially the position of the value if the list was sorted.

Calling sort( ) sorts the list into ascending order. The sorted list is the first thing returned. I put a ~ there as we don't really care about the sorted list, so we just throw the value away.

The second output param of sort is the mapping of the unsorted list onto the sorted one. That is, for each item in the unsorted list, it gives its position in the sorted one.

Edit Again: It sounds like you want "Fractional Ranking" from your description. There's nothing built into Matlab as far as I can see that does this directly, but there are files on the FEX. I've never used them, but there's one with a comprehensive description, so it seems likely to be a good bet: Rankings - File Exchange



标签: matlab vector