| # File src/library/stats/R/dist.R |
| # Part of the R package, https://www.R-project.org |
| # |
| # Copyright (C) 1995-2012 The R Core Team |
| # |
| # 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 |
| # https://www.R-project.org/Licenses/ |
| |
| dist <- function(x, method = "euclidean", diag = FALSE, upper = FALSE, p = 2) |
| { |
| ## account for possible spellings of euclid?an |
| if(!is.na(pmatch(method, "euclidian"))) |
| method <- "euclidean" |
| |
| METHODS <- c("euclidean", "maximum", |
| "manhattan", "canberra", "binary", "minkowski") |
| method <- pmatch(method, METHODS) |
| if(is.na(method)) |
| stop("invalid distance method") |
| if(method == -1) |
| stop("ambiguous distance method") |
| |
| x <- as.matrix(x) |
| N <- nrow(x) |
| attrs <- if(method == 6L) |
| list(Size = N, Labels = dimnames(x)[[1L]], Diag = diag, |
| Upper = upper, method = METHODS[method], |
| p = p, call = match.call(), class = "dist") |
| else |
| list(Size = N, Labels = dimnames(x)[[1L]], Diag = diag, |
| Upper = upper, method = METHODS[method], |
| call = match.call(), class = "dist") |
| .Call(C_Cdist, x, method, attrs, p) |
| } |
| |
| format.dist <- function(x, ...) format(as.vector(x), ...) |
| |
| as.matrix.dist <- function(x, ...) |
| { |
| size <- attr(x, "Size") |
| df <- matrix(0, size, size) |
| df[row(df) > col(df)] <- x |
| df <- df + t(df) |
| labels <- attr(x, "Labels") |
| dimnames(df) <- |
| if(is.null(labels)) list(seq_len(size), seq_len(size)) else list(labels,labels) |
| df |
| } |
| |
| |
| as.dist <- function(m, diag = FALSE, upper = FALSE) |
| UseMethod("as.dist") |
| |
| as.dist.default <- function(m, diag = FALSE, upper = FALSE) |
| { |
| if (inherits(m,"dist")) |
| ans <- m |
| else { ## matrix |-> dist |
| m <- as.matrix(m) |
| if(!is.numeric(m)) # coerce w/o losing attributes |
| storage.mode(m) <- "numeric" |
| p <- nrow(m) |
| if(ncol(m) != p) warning("non-square matrix") |
| ans <- m[row(m) > col(m)] |
| attributes(ans) <- NULL |
| if(!is.null(rownames(m))) |
| attr(ans,"Labels") <- rownames(m) |
| else if(!is.null(colnames(m))) |
| attr(ans,"Labels") <- colnames(m) |
| attr(ans,"Size") <- p |
| attr(ans, "call") <- match.call() |
| class(ans) <- "dist" |
| } |
| if(is.null(attr(ans,"Diag")) || !missing(diag)) |
| attr(ans,"Diag") <- diag |
| if(is.null(attr(ans,"Upper")) || !missing(upper)) |
| attr(ans,"Upper") <- upper |
| ans |
| } |
| |
| |
| print.dist <- |
| function(x, diag = NULL, upper = NULL, |
| digits = getOption("digits"), justify = "none", right = TRUE, ...) |
| { |
| if(length(x)) { |
| if(is.null(diag)) |
| diag <- if(is.null(a <- attr(x, "Diag"))) FALSE else a |
| if(is.null(upper)) |
| upper <- if(is.null(a <- attr(x,"Upper"))) FALSE else a |
| |
| m <- as.matrix(x) |
| cf <- format(m, digits = digits, justify = justify) |
| if(!upper) |
| cf[row(cf) < col(cf)] <- "" |
| if(!diag) |
| cf[row(cf) == col(cf)] <- "" |
| |
| ## Better: use an improved prettyNum() function -> ../../base/R/format.R |
| ##- if(any((i <- m == floor(m)))) |
| ##- cf[i] <- sub("0+$", "", cf[i]) |
| print(if(diag || upper) cf else cf[-1, -attr(x, "Size"), drop = FALSE], |
| quote = FALSE, right = right, ...) |
| } else { |
| cat(data.class(x),"(0)\n", sep = "") |
| } |
| invisible(x) |
| } |
| |
| labels.dist <- function (object, ...) attr(object,"Labels") |