Rev 50992 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
# File src/library/base/R/sort.R# Part of the R package, http://www.R-project.org## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## A copy of the GNU General Public License is available at# http://www.r-project.org/Licenses/sort <- function(x, decreasing = FALSE, ...){if(!is.logical(decreasing) || length(decreasing) != 1L)stop("'decreasing' must be a length-1 logical vector.\nDid you intend to set 'partial'?")UseMethod("sort")}sort.default <- function(x, decreasing = FALSE, na.last = NA, ...){## The first case includes factors.if(is.object(x)) x[order(x, na.last = na.last, decreasing = decreasing)]else sort.int(x, na.last = na.last, decreasing = decreasing, ...)}sort.int <-function(x, partial = NULL, na.last = NA, decreasing = FALSE,method = c("shell", "quick"), index.return = FALSE){if(isfact <- is.factor(x)) {if(index.return) stop("'index.return' only for non-factors")lev <- levels(x)nlev <- nlevels(x)isord <- is.ordered(x)x <- c(x)} else if(!is.atomic(x))stop("'x' must be atomic")if(has.na <- any(ina <- is.na(x))) {nas <- x[ina]x <- x[!ina]}if(index.return && !is.na(na.last))stop("'index.return' only for 'na.last = NA'")if(!is.null(partial)) {if(index.return || decreasing || isfact || !missing(method))stop("unsupported options for partial sorting")if(!all(is.finite(partial))) stop("non-finite 'partial'")y <- if(length(partial) <= 10L) {partial <- .Internal(qsort(partial, FALSE)).Internal(psort(x, partial))} else .Internal(qsort(x, FALSE))}else {nms <- names(x)method <- if(is.numeric(x)) match.arg(method) else "shell"switch(method,"quick" = {if(!is.null(nms)) {if(decreasing) x <- -xy <- .Internal(qsort(x, TRUE))if(decreasing) y$x <- -y$xnames(y$x) <- nms[y$ix]if (!index.return) y <- y$x} else {if(decreasing) x <- -xy <- .Internal(qsort(x, index.return))if(decreasing)if(index.return) y$x <- -y$x else y <- -y}},"shell" = {if(index.return || !is.null(nms)) {o <- sort.list(x, decreasing = decreasing)y <- if (index.return) list(x = x[o], ix = o) else x[o]## names(y) <- nms[o] # pointless!}elsey <- .Internal(sort(x, decreasing))})}if(!is.na(na.last) && has.na)y <- if(!na.last) c(nas, y) else c(y, nas)if(isfact)y <- (if (isord) ordered else factor)(y, levels=seq_len(nlev),labels=lev)y}order <- function(..., na.last = TRUE, decreasing = FALSE){z <- list(...)if(any(unlist(lapply(z, is.object)))) {z <- lapply(z, function(x) if(is.object(x)) xtfrm(x) else x)if(!is.na(na.last))return(do.call("order", c(z, na.last=na.last,decreasing=decreasing)))} else if(!is.na(na.last))return(.Internal(order(na.last, decreasing, ...)))## remove nasif(any(diff(sapply(z, length)) != 0L))stop("argument lengths differ")ans <- sapply(z, is.na)if(is.list(ans)) return(integer(0L)) # happens for 0-length inputok <- if(is.matrix(ans)) !apply(ans, 1, any) else !any(ans)if(all(!ok)) return(integer(0L))z[[1L]][!ok] <- NAans <- do.call("order", c(z, decreasing=decreasing))keep <- seq_along(ok)[ok]ans[ans %in% keep]}sort.list <- function(x, partial = NULL, na.last = TRUE, decreasing = FALSE,method = c("shell", "quick", "radix")){method <- match.arg(method)if(!is.atomic(x))stop("'x' must be atomic for 'sort.list'\nHave you called 'sort' on a list?")if(!is.null(partial)).NotYetUsed("partial != NULL")if(method == "quick") {if(is.factor(x)) x <- as.integer(x) # sort the internal codesif(is.numeric(x))return(sort(x, na.last = na.last, decreasing = decreasing,method = "quick", index.return = TRUE)$ix)else stop("method=\"quick\" is only for numeric 'x'")}if(method == "radix") {if(!typeof(x) == "integer") # do want to allow factors herestop("method=\"radix\" is only for integer 'x'")if(is.na(na.last))return(.Internal(radixsort(x[!is.na(x)], TRUE, decreasing)))elsereturn(.Internal(radixsort(x, na.last, decreasing)))}## method == "shell"if(is.na(na.last)) .Internal(order(TRUE, decreasing, x[!is.na(x)]))else .Internal(order(na.last, decreasing, x))}## xtfrm is now primitive## xtfrm <- function(x) UseMethod("xtfrm")xtfrm.default <- function(x)if(is.numeric(x)) unclass(x) else as.vector(rank(x, ties.method="min", na.last="keep"))xtfrm.factor <- function(x) as.integer(x) # primitive, so needs a wrapperxtfrm.Surv <- function(x)if(ncol(x) == 2L) order(x[,1L], x[,2L]) else order(x[,1L], x[,2L], x[,3L]) # needed by 'party'xtfrm.AsIs <- function(x){if(length(cl<- class(x)) > 1) oldClass(x) <- cl[-1L]NextMethod("xtfrm")}.gt <- function(x, i, j){xi <- x[i]; xj <- x[j]if (xi == xj) 0L else if(xi > xj) 1L else -1L;}.gtn <- function(x, strictly){n <- length(x)if(strictly) all(x[-1L] > x[-n]) else all(x[-1L] >= x[-n])}