From nilsson.henric at gmail.com  Tue Oct 20 16:26:02 2015
From: nilsson.henric at gmail.com (Henric Winell)
Date: Tue, 20 Oct 2015 16:26:02 +0200
Subject: [Rd] rank(, ties.method="last")
In-Reply-To: <22039.37791.6045.955899@stat.math.ethz.ch>
References: <CAM3-KjZ=d1a4sUFckw83RZu-phZffY7KvZeQ1WtAjNB6ysoeJw@mail.gmail.com>
	<22039.37791.6045.955899@stat.math.ethz.ch>
Message-ID: <56264EFA.80402@gmail.com>

Den 2015-10-09 kl. 12:14, skrev Martin Maechler:
>
>> I ran into a problem where I actually need rank(, ties.method="last"). It would
>> be great to have this feature in base and it's also simple to get (see below).
>
>> Thanks & cheers,
>> Marius
>
>
>> rank2 <- function (x, na.last = TRUE, ties.method = c("average",
>> "first", "last", # new "last"
>>      "random", "max", "min"))
>> {
>>      nas <- is.na(x)
>>      nm <- names(x)
>>      ties.method <- match.arg(ties.method)
>>      if (is.factor(x))
>>          x <- as.integer(x)
>>      x <- x[!nas]
>>      y <- switch(ties.method, average = , min = , max = .Internal(rank(x,
>>          length(x), ties.method)), first = sort.list(sort.list(x)),
>>          last = sort.list(sort.list(x, decreasing=TRUE), decreasing=TRUE), # change
>>          random = sort.list(order(x, stats::runif(sum(!nas)))))
>>      if (!is.na(na.last) && any(nas)) {
>>          yy <- NA
>>          NAkeep <- (na.last == "keep")
>>          if (NAkeep || na.last) {
>>              yy[!nas] <- y
>>              if (!NAkeep)
>>                  yy[nas] <- (length(y) + 1L):length(yy)
>>          }
>>          else {
>>              len <- sum(nas)
>>              yy[!nas] <- y + len
>>              yy[nas] <- seq_len(len)
>>          }
>>          y <- yy
>>          names(y) <- nm
>>      }
>>      else names(y) <- nm[!nas]
>>      y
>> }
>
>> ## MWE
>> x <- c(10, 11, 11, 12, 12, 13)
>> rank(x, ties.method="first")
>> rank2(x, ties.method="last")
>
> Indeed, this makes sense to me, and is easy enough to document
> and maintain, and preferable to asking useRs to use  rev(.) and
> similar "easy" (but somewhat costly for large data!)
> transformations to get the same....
>
> Or have (Marius Hofert and I) overlooked something obvious ?

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


Henric Winell



>
> Martin Maechler,
> ETH Zurich
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] rank(, ties.method="last")
Henric Winell