blob: b584dc44bae1554f67bf40d1216498ba94550396 [file] [log] [blame]
# 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")