>>>>> Suharto Anggono Suharto Anggono via R-devel <r-devel at
r-project.org>
>>>>> on Wed, 21 Oct 2015 22:44:57 -0700 writes:
> ------------------>>>>> Henric Winell <[hidden email]>
>>>>> on Wed, 21 Oct 2015 13:43:02 +0200 writes:
>> Den 2015-10-21 kl. 07:24, skrev Suharto Anggono Suharto Anggono via
R-devel:
>>> Marius Hofert-4------------------------------
>>>> Den 2015-10-09 kl. 12:14, skrev Martin Maechler:
>>>> I think so: the code above doesn't seem to do the right
thing. Consider
>>>> the following example:
>>>>
>>>> > x <- c(1, 1, 2, 3)
>>>> > rank2(x, ties.method = "last")
>>>> [1] 1 2 4 3
>>>>
>>>> That doesn't look right to me -- I had expected
>>>>
>>>> > rev(sort.list(x, decreasing = TRUE))
>>>> [1] 2 1 3 4
>>>>
>>>
>>> Indeed, well spotted, that seems to be correct.
>>>
>>>>
>>>> Henric Winell
>>>>
>>> ------------------------------
>>>
>>> In the particular example (of length 4), what is really wanted
is the following.
>>> ind <- integer(4)
>>> ind[sort.list(x, decreasing=TRUE)] <- 4:1
>>> ind
>> You don't provide the output here, but 'ind' is, of
course,
>>> ind
>> [1] 2 1 3 4
>>> The following gives the desired result:
>>> sort.list(rev(sort.list(x, decreasing=TRUE)))
>> And, again, no output, but
>>> sort.list(rev(sort.list(x, decreasing=TRUE)))
>> [1] 2 1 3 4
>> Why is it necessary to use 'sort.list' on the result from
>> 'rev(sort.list(...'?
> You can try all kind of code on this *too* simple example and do
> experiments. But let's approach this a bit more scientifically
> and hence systematically:
> Look at rank {the R function definition} to see that
> for the case of no NA's,
> rank(x, ties.method = "first') ===
sort.list(sort.list(x))
> If you assume that to be correct and want to define "last" to
be
> correct as well (in the sense of being "first"-consistent),
> it is clear that
> rank(x, ties.method = "last) ===
rev(sort.list(sort.list(rev(x))))
> must also be correct. I don't think that *any* of the proposals
> so far had a correct version [but the too simplistic examples
> did not show the problems].
> In R-devel (the R development) version of today, i.e., svn
> revision >= 69549, the implementation of ties.method =
"last'
> uses
> ## == rev(sort.list(sort.list(rev(x)))) :
> if(length(x) == 0) integer(0)
> else { i <- length(x):1L
> sort.list(sort.list(x[i]))[i] },
> which is equivalent to using rev() but a bit more efficient.
> Martin Maechler, ETH Zurich
> ------------------
> I'll defend that my code is correct in general.
> All comes from the fact that, if p is a permutation of 1:n,
> { ind <- integer(n); ind[p] <- 1:n; ind }
> gives the same result to
> sort.list(p)
Definitely; a known fact
(and that's how sort.list() -> order() is basically
implemented in R's C source code.)
> You can make sense of it like this. In ind[p] <- 1:n, ind[1] is the
position where p == 1. So, ind[1] is the position of the smallest element of p.
So, it is the first element of sort.list(p). Next elements follow.
> That's why 'sort.list' is used for
ties.method="first" and ties.method="random" in function
'rank' in R. When p gives the desired order,
> { ind <- integer(n); ind[p] <- 1:n; ind }
> gives ranks of the original elements based on the order. The original
element in position p[1] has rank 1, the original element in position p[2] has
rank 2, and so on.
> Now, I say that rev(sort.list(x, decreasing=TRUE)) gives the desired
order for ties.method="last". With the order, the elements are from
smallest to largest; for equal elements, elements are ordered by their positions
backwards.
You are right, Suharto :
Your proposed
sort.list(rev(sort.list(x, decreasing=TRUE)))
is also correct and the same as my
rev(sort.list(sort.list(rev(x))))
from above
nd your variant will even be slightly more efficient if implemented optimally !
Indeed, I was thinking wrongly when I wrote
"I don't think that *any* of the proposals so far had a correct
version"
because your proposal *was* correct.
I apologize for my wrong claim.
Best regards,
Martin