order.R
# Given a list whose ith element contains the indices
# of objects in the ith cluster, returns a vector whose ith
# element gives the cluster number of the ith object.
clus2memship <-
function(clusters) {
ans <- 1:length(unlist(clusters))
i <- 1
for (cl in clusters) {
ans[cl] <- i
i <- i+1
}
ans
}
# Given a vector whose ith elements gives the cluster number of the
# ith object, returns a list whose ith element contains the indices
# of objects in the ith cluster
memship2clus <-
function(memship) {
m <- sort(unique(memship))
index <- seq(along=memship)
sapply(m, function(g) index[memship==g],simplify=FALSE)
}
# This function accepts a "dist" or matrix of scores and
# returns an approximate Robinson ordering, used for scatterplot matrices.
#
order.single <-
function(merit,clusters=NULL) {
if (is.null(clusters))
order.hclust(merit, TRUE,method = "single")
else {
dis <- - merit
if (is.matrix(dis)) {
dism <- dis
dis <- as.dist(dis) }
else
dism <- as.matrix(dis)
n <- nrow(dism)
if (n <= 2)
clus <- 1:n
else {
cind <- col(matrix(0,n,n))
cind <- cind[lower.tri(cind)]
rind <- row(matrix(0,n,n))
rind <- rind[lower.tri(rind)]
d <- cbind(as.vector(dis),rind,cind)
d <- d[sort.list(d[,1],),]
if (is.null(clusters)) {
memship <- 1:n
clusters <- as.list(1:n)}
else memship <- clus2memship(clusters)
m <- length(dis)
for (i in 1:m) {
j <- memship[d[i,2]]
k <- memship[d[i,3]]
if (j!= k) {
if (j > k) {
r <- j
j <- k
k <- r}
memship[memship==k] <- j
clusj <- clusters[[j]]
clusk <- clusters[[k]]
dll <- dism[clusj[1], clusk[1]]
dlr <- dism[clusj[1], clusk[length(clusk)]]
drl <- dism[clusj[length(clusj)], clusk[1]]
drr <- dism[clusj[length(clusj)], clusk[length(clusk)]]
mind <- min(dll,dlr,drl,drr)
if (drl==mind)
NULL
else if (dlr==mind) {
clusj <-rev(clusj)
clusk <- rev(clusk)}
else if (dll ==mind)
clusj <- rev(clusj)
else clusk <- rev(clusk)
clusters[[j]] <- c(clusj,clusk)
}
if (length(clusters[[1]]) == n) break
}
clus <- clusters[[1]]}
clus}}
# This function accepts a "dist" or matrix of scores and
# returns an improved ordering, for parallel coordinate displays.
order.endlink <-
function(merit,clusters=NULL) {
dis <- - merit
if (is.matrix(dis)) {
dism <- dis
dis <- as.dist(dis) }
else {
dism <- as.matrix(dis)}
n <- nrow(dism)
if (n <= 2)
clus <- 1:n
else {
cind <- col(matrix(0,n,n))
cind <- cind[lower.tri(cind)]
rind <- row(matrix(0,n,n))
rind <- rind[lower.tri(rind)]
d <- cbind(as.vector(dis),rind,cind)
d <- d[sort.list(d[,1],),]
if (is.null(clusters)) {
memship <- 1:n
clusters <- as.list(1:n)}
else memship <- clus2memship(clusters)
m <- n*(n-1)/2
for (i in 1:m) {
j <- memship[d[i,2]]
k <- memship[d[i,3]]
if (!(j == k || j == -1 || k == -1)) {
if (j > k) {
r <- j
j <- k
k <- r
}
clusj <- clusters[[j]]
clusk <- clusters[[k]]
dll <- dism[clusj[1], clusk[1]]
dlr <- dism[clusj[1], clusk[length(clusk)]]
drl <- dism[clusj[length(clusj)], clusk[1]]
drr <- dism[clusj[length(clusj)], clusk[length(clusk)]]
mind <- min(dll,dlr,drl,drr)
if (drl==mind)
NULL
else if (dlr==mind) {
clusj <-rev(clusj)
clusk <- rev(clusk)}
else if (dll ==mind)
clusj <- rev(clusj)
else clusk <- rev(clusk)
clusters[[j]] <- c(clusj,clusk)
if (! (length(clusj) == 1))
memship[clusj[length(clusj)]] <- -1
if (! (length(clusk) == 1))
memship[clusk[1]] <- -1
memship[clusk[length(clusk)]] <- j
}
if (length(clusters[[1]]) == n) break
}
clus<- clusters[[1]]
}
clus
}
# This function takes a merit measure and clusters, either a vector
# giving the cluster number of the ith items, or a list whose ith element
# gives the indices of the elements in the ith cluster.
# Objects within a cluster are ordered with within.order
# and clusters are ordered with between.order.
#
order.clusters <- function(merit,clusters,within.order = order.single,
between.order= order.single,...) {
if (!is.list(clusters))
clusters <- memship2clus(clusters)
if (!is.matrix(merit))
merit <- as.matrix(merit)
if (!is.null(within.order)) {
clusl <- lapply(clusters, function(g)
within.order(merit[g,g],...))
newclusl <- lapply(1:length(clusters),function(i) clusters[[i]][clusl[[i]]])
}
else newclusl <- clusters
if (!is.null(between.order))
between.order(merit,newclusl)
else unlist(newclusl)
}