17 Code
17.1 R Code
17.1.1 Driver
source ("gifiEngine.R")
source ("gifiUtilities.R")
source ("gifiWrappers.R")
source ("gifiStructures.R")
source ("aspectEngine.R")
source ("theAspects.R")
source ("matrix.R")
source ("coneRegression.R")
source ("splineBasis.R")
source ("coding.R")
17.1.2 Engine
gifiEngine <-
function (gifi,
ndim,
itmax,
eps,
seed,
verbose) {
set.seed (seed)
nobs <- nrow (as.matrix (gifi[[1]][[1]]$data))
nsets <- length (gifi)
nvars <- sum (sapply (gifi, length))
itel <- 1
if (nvars == 1)
stop("a gifiAnalysis needs more than one variable")
x <- matrix (rnorm (nobs * ndim), nobs, ndim)
x <- gsRC (center (x))$q
xGifi <- xGifi (gifi, x)
fold <- 0
asets <- 0
for (i in 1:nsets) {
gifiSet <- gifi[[i]]
xGifiSet <- xGifi[[i]]
nvarset <- length (gifiSet)
ha <- matrix (0, nobs, ndim)
activeCount <- 0
for (j in 1:nvarset) {
if (gifiSet[[j]]$active) {
activeCount <- activeCount + 1
ha <- ha + xGifiSet[[j]]$scores
}
}
if (activeCount > 0) {
asets <- asets + 1
fold <- fold + sum ((x - ha) ^ 2)
}
}
fold <- fold / (asets * ndim)
repeat {
xz <- matrix(0, nobs, ndim)
fnew <- fmid <- 0
for (i in 1:nsets) {
gifiSet <- gifi[[i]]
xGifiSet <- xGifi[[i]]
nvarset <- length (gifiSet)
hh <- matrix (0, nobs, 0)
activeCount <- 0
for (j in 1:nvarset) {
if (gifiSet[[j]]$active) {
activeCount <- activeCount + 1
hh <- cbind (hh, xGifiSet[[j]]$transform)
}
}
if (activeCount == 0)
next
lf <- lsRC (hh, x)
aa <- lf$solution
rs <- lf$residuals
kappa <- max (eigen (crossprod (aa))$values)
fmid <- fmid + sum (rs ^ 2)
target <- hh + tcrossprod (rs, aa) / kappa
hh <- matrix (0, nobs, 0)
scopies <- 0
for (j in 1:nvarset) {
gifiVar <- gifiSet[[j]]
jdata <- gifiVar$data
jbasis <- gifiVar$basis
jcopies <- gifiVar$copies
jdegree <- gifiVar$degree
jties <- gifiVar$ties
jmissing <- gifiVar$missing
jordinal <- gifiVar$ordinal
ja <- aa[scopies + 1:jcopies, , drop = FALSE]
jtarget <- target[, scopies + 1:jcopies, drop = FALSE]
hj <-
gifiTransform (
data = jdata,
target = jtarget,
basis = jbasis,
copies = jcopies,
degree = jdegree,
ordinal = jordinal,
ties = jties,
missing = jmissing
)
hj <- gsRC(normalize (center (hj)))$q
sc <- hj %*% ja
xGifi[[i]][[j]]$transform <- hj
xGifi[[i]][[j]]$weights <- ja
xGifi[[i]][[j]]$scores <- sc
xGifi[[i]][[j]]$quantifications <-
lsRC(jbasis, sc)$solution
activeCount <- 0
if (gifiSet[[j]]$active) {
activeCount <- activeCount + 1
hh <- cbind (hh, hj)
}
scopies <- scopies + jcopies
}
if (activeCount > 0) {
ha <- hh %*% aa
xz <- xz + ha
fnew <- fnew + sum ((x - ha) ^ 2)
}
}
fmid <- fmid / (asets * ndim)
fnew <- fnew / (asets * ndim)
if (verbose)
cat(
"Iteration: ",
formatC (itel, width = 3, format = "d"),
"fold: ",
formatC (
fold,
digits = 8,
width = 12,
format = "f"
),
"fmid: ",
formatC (
fmid,
digits = 8,
width = 12,
format = "f"
),
"fnew: ",
formatC (
fnew,
digits = 8,
width = 12,
format = "f"
),
"\n"
)
if (((itel == itmax) || ((fold - fnew) < eps)) && (itel > 1))
break
itel <- itel + 1
fold <- fnew
x <- gsRC (center (xz))$q
}
return (list (
f = fnew,
ntel = itel,
x = x,
xGifi = xGifi
))
}
gifiTransform <-
function (data,
target,
basis,
copies,
degree,
ordinal,
ties,
missing) {
nobs <- nrow (as.matrix (data))
h <- matrix (0, nobs, copies)
if (degree == -1) {
if (ordinal) {
h[, 1] <-
coneRegression (
data = data,
target = target[, 1],
type = "c",
ties = ties,
missing = missing
)
}
else {
h[, 1] <-
coneRegression (
data = data,
target = target[, 1],
basis = basis,
type = "s",
missing = missing
)
}
}
if (degree >= 0) {
if (ordinal) {
h[, 1] <-
coneRegression (
data = data,
target = target[, 1],
basis = basis,
type = "i",
ties = ties,
missing = missing
)
}
else {
h[, 1] <-
coneRegression (
data = data,
target = target[, 1],
basis = basis,
type = "s",
ties = ties,
missing = missing
)
}
}
if (copies > 1) {
for (l in 2:copies)
h[, l] <-
coneRegression (
data = data,
target = target[, l],
basis = basis,
type = "s",
ties = ties,
missing = missing
)
}
return (h)
}
17.1.3 Aspect Engine
aspectEngine <-
function (gifi,
afunc,
eps = 1e-6,
itmax = 100,
verbose = 1,
monotone = FALSE,
...) {
nsets <- length (gifi)
for (i in 1:nsets) {
gifiSet <- gifi[[i]]
nvars <- length (gifiSet)
for (j in 1:nvars) {
gifiVar <- gifiSet[[j]]
q <- gifiVar$qr$q
}
}
itel <- 1
tdata <- matrix (0, n, m)
for (j in 1:m) {
tdata[, j] <- bd$x[[j]]
}
tdata <- apply (tdata, 2, function (z)
z - mean (z))
tdata <- apply (tdata, 2, function (z)
z / sqrt (sum (z ^ 2)))
corr <- crossprod (tdata)
af <- afunc(corr, ...)
fold <- af$f
g <- af$g
repeat {
for (j in 1:m) {
target <- drop (tdata[, -j] %*% g[-j, j])
k <- bd$b[[j]]
v <- bd$v[[j]]
u <- drop (crossprod(k, target))
s0 <- sum(target * tdata[, j])
if (ordinal[j]) {
ns <- nnls(v, u)
rr <- residuals(ns)
tt <- drop(k %*% rr)
} else
tt <- drop (k %*% u)
tt <- tt - mean (tt)
sq <- sum(tt ^ 2)
if (sq > 1e-15) {
tt <- tt / sqrt (sq)
tdata[, j] <- tt
}
s1 <- sum(target * tdata[, j])
if (verbose > 1)
cat (
"**** Variable",
formatC(j, width = 3, format = "d"),
"Before",
formatC(
s0,
digits = 8,
width = 12,
format = "f"
),
"After",
formatC(
s1,
digits = 8,
width = 12,
format = "f"
),
"\n"
)
if (!monotone) {
corr <- cor (tdata)
af <- afunc (corr, ...)
fnew <- af$f
g <- af$g
}
}
if (monotone) {
corr <- cor (tdata)
af <- afunc (corr, ...)
fnew <- af$f
g <- af$g
}
if (verbose > 0)
cat(
"Iteration: ",
formatC (itel, width = 3, format = "d"),
"fold: ",
formatC (
fold,
digits = 8,
width = 12,
format = "f"
),
"fnew: ",
formatC (
fnew,
digits = 8,
width = 12,
format = "f"
),
"\n"
)
if ((itel == itmax) || ((fnew - fold) < eps))
break
itel <- itel + 1
fold <- fnew
}
return (list (
tdata = tdata,
f = fnew,
r = corr,
g = g
))
}
17.1.4 Some Aspects
maxeig <- function (r, p) {
e <- eigen (r)
f <- sum (e$values[1:p])
g <- tcrossprod(e$vectors[,1:p])
return (list (f = f, g = g))
}
maxcor <- function (r, p) {
f <- sum (r ^ p)
g <- p * (r ^ (p - 1))
return (list (f = f, g = g))
}
maxabs <- function (r, p) {
f <- sum (abs(r) ^ p)
g <- p * (abs(r) ^ (p - 1)) * sign(r)
return (list (f = f, g = g))
}
maxdet <- function (r) {
f <- -log(det (r))
g <- -solve(r)
return (list (f = f, g = g))
}
maxsmc <- function (r, p) {
beta <- solve (r[-p,-p], r[p,-p])
f <- sum (beta * r[p,-p])
h <- rep (1, nrow (r))
h[-p] <- -beta
g <- -outer (h, h)
return (list (f = f, g = g))
}
maxsum <- function (r, p) {
f <- sum (sqrt (r ^ 2 + p))
g <- r / sqrt (r ^ 2 + p)
return (list (f = f, g = g))
}
maximage <- function (r) {
n <- nrow(r)
f <- 0
g <- matrix (0, n, n)
for (p in 1:n) {
beta <- solve (r[-p,-p], r[p,-p])
f <- f + sum (beta * r[p,-p])
h <- rep (1, nrow (r))
h[-p] <- -beta
g <- g - outer (h, h)
}
return (list (f = f, g = g))
}
maxfac <- function (r, p) {
fa <- factanal (NULL, p, covmat = r, rotation = "none")
s <- tcrossprod (fa$loadings) + diag (fa$unique)
g <- - solve (s)
f <- -log(det (s)) + sum (g * r)
return (list (f = f, g = g))
}
17.1.5 Structures
makeGifiVariable <-
function (data,
knots,
degree,
ordinal,
ties,
copies,
missing,
name) {
there <- which (!is.na (data))
notthere <- which (is.na (data))
nmis <- length (notthere)
nobs <- length (data)
if (length (there) == 0)
stop ("a gifiVariable cannot be completely missing")
work <- data[there]
if (degree == -1) {
type <- "categorical"
basis <- makeIndicator (work)
if (ncol (basis) == 1) {
stop ("a gifiVariable must have more than one category")
}
if (ncol (basis) == 2) {
type <- "binary"
}
}
if (degree >= 0) {
if (length (knots) == 0)
type <- "polynomial"
else
type <- "splinical"
basis <- bsplineBasis (work, degree, knots)
}
if (nmis > 0)
basis <- makeMissing (data, basis, missing)
copies <- min (copies, ncol (basis) - 1)
qr <- gsRC (center (basis))
if (qr$rank == 0)
stop ("a gifiVariable cannot be completely zero")
return (structure (
list (
data = data,
basis = basis,
qr = qr,
copies = copies,
degree = degree,
ties = ties,
ordinal = ordinal,
name = name,
type = type
),
class = "gifiVariable"
))
}
makeGifiSet <-
function (data,
knots,
degrees,
ordinal,
ties,
copies,
missing,
names) {
nvars <- ncol (data)
varList <- as.list (1:nvars)
for (i in 1:nvars) {
varList[[i]] <-
makeGifiVariable (
data = data[, i],
knots = knots[[i]],
degree = degrees[i],
ordinal = ordinal[i],
ties[i],
copies = copies[i],
missing = missing[i],
name = names[i]
)
}
return (structure (varList, class = "gifiSet"))
}
makeGifi <-
function (data,
knots,
degrees,
ordinal,
ties,
copies,
missing,
names,
sets) {
nsets <- max (sets)
setList <- as.list (1:nsets)
for (i in 1:nsets) {
k <- which (sets == i)
setList [[i]] <-
makeGifiSet (
data = data[, k, drop = FALSE],
knots = knots[k],
degrees = degrees[k],
ordinal = ordinal[k],
ties = ties[k],
copies = copies[k],
missing = missing[k],
names = names[k]
)
}
return (structure (setList, class = "gifi"))
}
xGifiVariable <- function (gifiVariable, ndim) {
basis <- gifiVariable$basis
nbas <- ncol (basis)
nobs <- length (gifiVariable$data)
copies <- gifiVariable$copies
transform <- matrix (0, nobs, copies)
transform[, 1] <- drop(basis %*% (1:nbas))
if (copies > 1) {
for (i in 2:copies)
transform[, i] <- drop (basis %*% rnorm (nbas))
}
transform <- gsRC (normalize (center (transform)))$q
nbas <- ncol (transform)
weights <- matrix (rnorm (nbas * ndim), nbas, ndim)
scores <- transform %*% weights
quantifications <- lsRC (basis, scores)$solution
return (structure (
list(
transform = transform,
weights = weights,
scores = scores,
quantifications = quantifications
),
class = "xGifiVariable"
))
}
xGifiSet <- function (gifiSet, ndim) {
nvars <- length (gifiSet)
varList <- as.list (1:nvars)
for (i in 1:nvars) {
varList[[i]] <- xGifiVariable (gifiSet[[i]], ndim)
}
return (structure (varList, class = "xGifiSet"))
}
xGifi <- function (gifi, ndim) {
nsets <- length (gifi)
setList <- as.list (1:nsets)
for (i in 1:nsets) {
setList[[i]] <- xGifiSet (gifi[[i]], ndim)
}
return (structure (setList, class = "xGifi"))
}
17.1.6 Wrappers
homals <-
function (data,
knots = knotsD (data),
degrees = -1,
ordinal = FALSE,
ndim = 2,
ties = "s",
missing = "m",
names = colnames (data, do.NULL = FALSE),
active = TRUE,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
nvars <- ncol (data)
g <- makeGifi (
data = data,
knots = knots,
degrees = reshape (degrees, nvars),
ordinal = reshape (ordinal, nvars),
ties = reshape (ties, nvars),
copies = rep (ndim, ncol (data)),
missing = reshape (missing, nvars),
active = reshape (active, nvars),
names = names,
sets = 1:nvars
)
h <- gifiEngine(
gifi = g,
ndim = ndim,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
a <- v <- z <- d <- y <- o <- as.list (1:ncol(data))
dsum <- matrix (0, ndim, ndim)
nact <- 0
for (j in 1:nvars) {
jgifi <- h$xGifi[[j]][[1]]
v[[j]] <- jgifi$transform
a[[j]] <- jgifi$weights
y[[j]] <- jgifi$scores
z[[j]] <- jgifi$quantifications
cy <- crossprod (y[[j]])
if (g[[j]][[1]]$active) {
dsum <- dsum + cy
nact <- nact + 1
}
d[[j]] <- cy
o[[j]] <- crossprod (h$x, v[[j]])
}
return (structure (
list (
transform = v,
rhat = corList (v),
objectscores = h$x,
scores = y,
quantifications = z,
dmeasures = d,
lambda = dsum / nact,
weights = a,
loadings = o,
ntel = h$ntel,
f = h$f
),
class = "homals"
))
}
corals <-
function (data,
ftype = TRUE,
xknots = NULL,
yknots = NULL,
xdegree = -1,
ydegree = -1,
xordinal = FALSE,
yordinal = FALSE,
xties = "s",
yties = "s",
xmissing = "m",
ymissing = "m",
xname = "X",
yname = "Y",
ndim = 2,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
if (ftype) {
xy <- preCorals (as.matrix(data))
x <- xy[, 1, drop = FALSE]
y <- xy[, 2, drop = FALSE]
} else {
x <- data[, 1, drop = FALSE]
y <- data[, 2, drop = FALSE]
}
if (is.null(xknots))
xknots <- knotsD(x)
if (is.null(yknots))
yknots <- knotsD(y)
g <- makeGifi (
data = cbind (x, y),
knots = c(xknots, yknots),
degrees = c(xdegree, ydegree),
ordinal = c(xordinal, yordinal),
ties = c(xties, yties),
copies = c(ndim, ndim),
missing = c(xmissing, ymissing),
active = c(TRUE, TRUE),
names = c(xname, yname),
sets = c(1, 2)
)
h <- gifiEngine(
gifi = g,
ndim = ndim,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
xg <- h$xGifi[[1]][[1]]
yg <- h$xGifi[[2]][[1]]
return (structure (
list(
burt = crossprod (cbind(g[[1]][[1]]$basis, g[[2]][[1]]$basis)),
objectscores = h$x,
xtransform = postCorals (x, xg$transform),
ytransform = postCorals (y, yg$transform),
rhat = cor (cbind (xg$transform, yg$transform)),
xweights = xg$weights,
yweights = yg$weights,
xscores = postCorals (x, xg$scores),
yscores = postCorals (y, yg$scores),
xdmeasure = crossprod (xg$scores),
ydmeasure = crossprod (yg$scores),
xquantifications = xg$quantifications,
yquantifications = yg$quantifications,
xloadings = crossprod (xg$transform, h$x),
yloadings = crossprod (yg$transform, h$x),
lambda = (crossprod (xg$scores) + crossprod (yg$scores)) / 2,
ntel = h$ntel,
f = h$f
),
class = "corals"
))
}
coranals <- function () {
}
morals <-
function (x,
y,
xknots = knotsQ(x),
yknots = knotsQ(y),
xdegrees = 2,
ydegrees = 2,
xordinal = TRUE,
yordinal = TRUE,
xties = "s",
yties = "s",
xmissing = "m",
ymissing = "m",
xnames = colnames (x, do.NULL = FALSE),
ynames = "Y",
xactive = TRUE,
xcopies = 1,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
npred <- ncol (x)
nobs <- nrow (x)
xdegrees <- reshape (xdegrees, npred)
xordinal <- reshape (xordinal, npred)
xties <- reshape (xties, npred)
xmissing <- reshape (xmissing, npred)
xactive <- reshape (xactive, npred)
xcopies <- reshape (xcopies, npred)
g <- makeGifi (
data = cbind (x, y),
knots = c (xknots, yknots),
degrees = c (xdegrees, ydegrees),
ordinal = c (xordinal, yordinal),
sets = c (rep(1, npred), 2),
copies = c (xcopies, 1),
ties = c (xties, yties),
missing = c (xmissing, ymissing),
active = c (xactive, TRUE),
names = c (xnames, ynames)
)
h <- gifiEngine(
gifi = g,
ndim = 1,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
xhat <- matrix (0, nobs, 0)
for (j in 1:npred)
xhat <- cbind (xhat, h$xGifi[[1]][[j]]$transform)
yhat <- h$xGifi[[2]][[1]]$transform
rhat <- cor (cbind (xhat, yhat))
qxy <- lsRC(xhat, yhat)$solution
ypred <- xhat %*% qxy
yres <- yhat - ypred
smc <- sum (yhat * ypred)
return (structure (
list (
objscores = h$x,
xhat = xhat,
yhat = yhat,
rhat = rhat,
beta = qxy,
ypred = ypred,
yres = yres,
smc = smc,
ntel = h$ntel,
f = h$f
),
class = "morals"
))
}
princals <-
function (data,
knots = knotsQ (data),
degrees = 2,
ordinal = TRUE,
copies = 1,
ndim = 2,
ties = "s",
missing = "m",
names = colnames (data, do.NULL = FALSE),
active = TRUE,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
aname <- deparse (substitute (data))
nvars <- ncol (data)
nobs <- nrow (data)
g <- makeGifi (
data = data,
knots = knots,
degrees = reshape (degrees, nvars),
ordinal = reshape (ordinal, nvars),
sets = 1:nvars,
copies = reshape (copies, nvars),
ties = reshape (ties, nvars),
missing = reshape (missing, nvars),
active = reshape (active, nvars),
names = names
)
h <- gifiEngine(
gifi = g,
ndim = ndim,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
a <- v <- z <- d <- y <- o <- as.list (1:nvars)
dsum <- matrix (0, ndim, ndim)
for (j in 1:nvars) {
jgifi <- h$xGifi[[j]][[1]]
v[[j]] <- jgifi$transform
a[[j]] <- jgifi$weights
y[[j]] <- jgifi$scores
z[[j]] <- jgifi$quantifications
cy <- crossprod (y[[j]])
dsum <- dsum + cy
d[[j]] <- cy
o[[j]] <- crossprod (h$x, v[[j]])
}
return (structure (
list (
transform = v,
rhat = corList (v),
objectscores = h$x,
scores = y,
quantifications = z,
dmeasures = d,
lambda = dsum / ncol (data),
weights = a,
loadings = o,
ntel = h$ntel,
f = h$f
),
class = "princals"
))
}
criminals <-
function (x,
y,
xknots = knotsQ(x),
yknots = knotsD(y),
xdegrees = 2,
ydegrees = -1,
xordinal = TRUE,
yordinal = FALSE,
xcopies = 1,
xties = "s",
yties = "s",
xmissing = "m",
ymissing = "m",
xactive = TRUE,
xnames = colnames (x, do.NULL = FALSE),
ynames = "Y",
ndim = 2,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
aname <- deparse (substitute (data))
npred <- ncol (x)
nobs <- nrow (x)
g <- makeGifi (
data = cbind (x, y),
knots = c(xknots, yknots),
degrees = c (reshape (xdegrees, npred), ydegrees),
ordinal = c (reshape (xordinal, npred), yordinal),
sets = c (rep(1, npred), 2),
copies = c (reshape (xcopies, npred), length (unique (y))),
ties = c (reshape (xties, npred), yties),
missing = c (reshape (xmissing, npred), ymissing),
active = c (reshape (xactive, npred), TRUE),
names = c(xnames, ynames)
)
h <- gifiEngine(
gifi = g,
ndim = ndim,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
x <- matrix (0, nobs, 0)
for (j in 1:npred)
x <- cbind (x, h$xGifi[[1]][[j]]$transform)
y <- as.vector(y)
g <- ifelse (outer (y, unique (y), "=="), 1, 0)
d <- colSums (g)
v <- crossprod (x)
u <- crossprod (g, x)
b <- crossprod (u, (1 / d) * u)
w <- v - b
e <- eigen (v)
k <- e$vectors
l <- sqrt (abs (e$values))
l <- ifelse (l < 1e-7, 0, 1 / l)
f <- eigen (outer(l, l) * crossprod (k, b %*% k))
a <- k %*% (l * f$vectors)
z <- x %*% a
u <- (1 / d) * crossprod (g, x)
return (structure (
list(
objectscores = h$x,
xhat = x,
loadings = a,
scores = z,
groupmeans = u,
bwratios = f$values,
ntel = h$ntel,
f = h$f
),
class = "criminals"
))
}
canals <-
function (x,
y,
xknots = knotsQ(x),
yknots = knotsQ(y),
xdegrees = rep(2, ncol(x)),
ydegrees = rep(2, ncol(y)),
xordinal = rep (TRUE, ncol (x)),
yordinal = rep (TRUE, ncol (y)),
xcopies = rep (1, ncol (x)),
ycopies = rep (1, ncol (y)),
ndim = 2,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
h <- gifiEngine(
data = cbind (x, y),
knots = c(xknots, yknots),
degrees = c(xdegrees, ydegrees),
ordinal = c(xordinal, yordinal),
sets = c(rep(1, ncol(x)), rep(2, ncol (y))),
copies = c(xcopies, ycopies),
ndim = ndim,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
x <- h$h[, 1:sum(xcopies)]
y <- h$h[, -(1:sum(xcopies))]
u <- crossprod (x)
v <- crossprod (y)
w <- crossprod (x, y)
a <- solve (chol (u))
b <- solve (chol (v))
s <- crossprod (a, w %*% b)
r <- svd (s)
xw <- a %*% (r$u)
yw <- b %*% (r$v)
xs <- x %*% xw
ys <- y %*% yw
xl <- crossprod (x, xs)
yl <- crossprod (y, ys)
return (structure (
list(
xhat = x,
yhat = y,
rhat = cor (cbind (x, y)),
cancors = r$d,
xweights = xw,
yweights = yw,
xscores = xs,
yscores = ys,
xloadings = xl,
yloadings = yl,
ntel = h$ntel,
f = h$f
),
class = "canals"
))
}
overals <-
function (data,
sets,
copies,
knots = knotsQ (data),
degrees = rep (2, ncol (data)),
ordinal = rep (TRUE, ncol (data)),
ndim = 2,
itmax = 1000,
eps = 1e-6,
seed = 123,
verbose = FALSE) {
h <- gifiEngine(
data = data,
knots = knots,
degrees = degrees,
ordinal = ordinal,
sets = sets,
copies = copies,
ndim = ndim,
itmax = itmax,
eps = eps,
seed = seed,
verbose = verbose
)
xhat <- h$h
rhat <- cor (xhat)
a <- h$a
y <- xhat
for (j in 1:ncol(data)) {
k <- (1:ndim) + (j - 1) * ndim
y[, k] <- xhat[, k] %*% a[k,]
}
return (structure (
list (
xhat = xhat,
rhat = rhat,
objscores = h$x,
quantifications = y,
ntel = h$ntel,
f = h$f
),
class = "overals"
))
}
primals <- function () {
}
addals <- function () {
}
pathals <- function () {
}
17.1.7 Splines
bsplineBasis <- function (x, degree, innerknots, lowknot = min(x,innerknots), highknot = max(x,innerknots)) {
innerknots <- unique (sort (innerknots))
knots <- c(rep(lowknot, degree + 1), innerknots, rep(highknot, degree + 1))
n <- length (x)
m <- length (innerknots) + 2 * (degree + 1)
nf <- length (innerknots) + degree + 1
basis <- rep (0, n * nf)
res <- .C("splinebasis", d = as.integer(degree),
n = as.integer(n), m = as.integer (m), x = as.double (x), knots = as.double (knots), basis = as.double(basis))
basis <- matrix (res$basis, n, nf)
basis <- basis[,which(colSums(basis) > 0)]
return (basis)
}
knotsQ <- function (x, n = rep (5, ncol (x))) {
do <- function (i) {
y <- quantile (x[, i], probs = seq(0, 1, length = max (2, n[i])))
return (y[-c(1, length(y))])
}
lapply (1:ncol(x), function (i)
do (i))
}
knotsR <- function (x, n = rep (5, ncol (x))) {
do <- function (i) {
y <- seq (min(x[, i]), max(x[, i]), length = max (2, n[i]))
return (y[-c(1, length(y))])
}
lapply (1:ncol(x), function (i)
do (i))
}
knotsE <- function (x) {
lapply (1:ncol(x), function (i)
numeric(0))
}
knotsD <- function (x) {
do <- function (i) {
y <- sort (unique (x[, i]))
return (y[-c(1, length(y))])
}
lapply (1:ncol(x), function (i)
do (i))
}
17.1.8 Gram-Schmidt
gsRC <- function (x, eps = 1e-10) {
n <- nrow (x)
m <- ncol (x)
h <-
.C(
"gsC",
x = as.double(x),
r = as.double (matrix (0, m, m)),
n = as.integer (n),
m = as.integer (m),
rank = as.integer (0),
pivot = as.integer (1:m),
eps = as.double (eps)
)
rank = h$rank
return (list (
q = matrix (h$x, n, m)[, 1:rank, drop = FALSE],
r = matrix (h$r, m, m)[1:rank, , drop = FALSE],
rank = rank,
pivot = h$pivot
))
}
lsRC <- function (x, y, eps = 1e-10) {
n <- nrow (x)
m <- ncol (x)
h <- gsRC (x, eps)
l <- h$rank
p <- order (h$pivot)
k <- 1:l
q <- h$q
a <- h$r[, k, drop = FALSE]
v <- h$r[, -k, drop = FALSE]
u <- crossprod (q, y)
b <- solve (a, u)
res <- drop (y - q %*% u)
s <- sum (res ^ 2)
b <- rbind(b, matrix (0, m - l, ncol(y)))[p, , drop = FALSE]
if (l == m) {
e <- matrix(0, m, 1)
} else {
e <- rbind (-solve(a, v), diag(m - l))[p, , drop = FALSE]
}
return (list (
solution = b,
residuals = res,
minssq = s,
nullspace = e,
rank = l,
pivot = p
))
}
nullRC <- function (x, eps = 1e-10) {
h <- gsRC (x, eps = eps)
rank <- h$rank
r <- h$r
m <- ncol (x)
t <- r[, 1:rank, drop = FALSE]
s <- r[, -(1:rank), drop = FALSE]
if (rank == m)
return (matrix(0, m, 1))
else {
nullspace <- rbind (-solve(t, s), diag (m - rank))[order(h$pivot), , drop = FALSE]
return (gsRC (nullspace)$q)
}
}
ginvRC <- function (x, eps = 1e-10) {
h <- gsRC (x, eps)
p <- order(h$pivot)
q <- h$q
s <- h$r
z <- crossprod (s, (solve (tcrossprod(s), t(q))))
return (z[p, , drop = FALSE])
}
17.1.9 Cone regression
dyn.load ("pava.so")
amalgm <- function (x, w = rep (1, length (x))) {
n <- length (x)
a <- rep (0, n)
b <- rep (0, n)
y <- rep (0, n)
lf <-
.Fortran (
"AMALGM",
n = as.integer (n),
x = as.double (x),
w = as.double (w),
a = as.double (a),
b = as.double (b),
y = as.double (y),
tol = as.double(1e-15),
ifault = as.integer(0)
)
return (lf$y)
}
isotone <-
function (x,
y,
w = rep (1, length (x)),
ties = "s") {
there <- which (!is.na (x))
notthere <- which (is.na (x))
xthere <- x[there]
f <- sort(unique(xthere))
g <- lapply(f, function (z)
which(x == z))
n <- length (x)
k <- length (f)
if (ties == "s") {
w <- sapply (g, length)
h <- lapply (g, function (z)
y[z])
m <- sapply (h, sum) / w
r <- amalgm (m, w)
s <- rep (0, n)
for (i in 1:k)
s[g[[i]]] <- r[i]
s[notthere] <- y[notthere]
}
if (ties == "p") {
h <- lapply (g, function (z)
y[z])
m <- rep (0, n)
s <- rep (0, n)
for (i in 1:k) {
ii <- order (h[[i]])
g[[i]] <- g[[i]][ii]
h[[i]] <- h[[i]][ii]
}
m <- unlist (h)
r <- amalgm (m, w)
s[there] <- r[order (unlist (g))]
s[notthere] <- y[notthere]
}
if (ties == "t") {
w <- sapply (g, length)
h <- lapply (g, function (x)
y[x])
m <- sapply (h, sum) / w
r <- amalgm (m, w)
s <- rep (0, n)
for (i in 1:k)
s[g[[i]]] <- y[g[[i]]] + (r[i] - m[i])
s[notthere] <- y[notthere]
}
return (s)
}
coneRegression <-
function (data,
target,
basis = matrix (data, length(data), 1),
type = "i",
ties = "s",
missing = "m",
itmax = 1000,
eps = 1e-6) {
itel <- 1
there <- which (!is.na (data))
notthere <- which (is.na (data))
nmis <- length (notthere)
solution <- rep(0, length (data))
wdata <- data[there]
wtarget <- target[there]
wbasis <- basis [there, ]
if (type == "s") {
solution <- drop (basis %*% lsRC (basis, target)$solution)
}
if ((type == "c") && (missing != "a")) {
solution[there] <- isotone (x = wdata, y = wtarget, ties = ties)
if (nmis > 0) {
if (missing == "m")
solution[notthere] <- target[notthere]
if (missing == "s")
solution[notthere] <- mean (target[notthere])
}
}
if ((type == "i") || ((type == "c") && (missing == "a"))) {
solution <-
dykstra (
target = target,
basis = basis,
data = data,
ties = ties,
itmax = itmax,
eps = eps
)
}
return (solution)
}
dykstra <- function (target, basis, data, ties, itmax, eps) {
x0 <- target
itel <- 1
a <- b <- rep (0, length (target))
fold <- Inf
repeat {
x1 <- drop (basis %*% lsRC (basis, x0 - a)$solution)
a <- a + x1 - x0
x2 <- isotone (data, x1 - b, ties = ties)
b <- b + x2 - x1
fnew <- sum ((target - (x1 + x2) / 2) ^ 2)
xdif <- max (abs (x1 - x2))
if ((itel == itmax) || (xdif < eps))
break
itel <- itel + 1
x0 <- x2
fold <- fnew
}
return ((x1 + x2) / 2)
}
17.1.10 Coding
dyn.load("coding.so")
decode <- function(cell, dims) {
if (length(cell) != length(dims)) {
stop("Dimension error")
}
if (any(cell > dims) || any (cell < 1)) {
stop("No such cell")
}
.Call("DECODE", as.integer(cell), as.integer(dims))
}
encode <- function(ind, dims) {
if (length(ind) > 1) {
stop ("Dimension error")
}
if ((ind < 1) || (ind > prod(dims))) {
stop ("No such cell")
}
.Call("ENCODE", as.integer(ind), as.integer(dims))
}
17.1.11 Utilities
makeNumeric <- function (x) {
do <- function (y) {
u <- unique (y)
return (drop (ifelse (outer (y, u, "=="), 1, 0) %*% (1:length (u))))
}
if (is.vector (x)) {
return (do (x))
}
else {
return (apply (x, 2, do))
}
}
center <- function (x) {
do <- function (z) {
z - mean (z)
}
if (is.matrix (x))
return (apply (x, 2, do))
else
return (do (x))
}
normalize <- function (x) {
do <- function (z) {
z / sqrt (sum (z ^ 2))
}
if (is.matrix (x))
return (apply (x, 2, do))
else
return (do (x))
}
makeMissing <- function (data, basis, missing) {
there <- which (!is.na (data))
notthere <- which (is.na (data))
nmis <- length (notthere)
nobs <- length (data)
ndim <- ncol (basis)
if (missing == "m") {
abasis <- matrix (0, nobs, ndim + nmis)
abasis [there, 1:ndim] <- basis
abasis [notthere, ndim + 1:nmis] <- diag(nmis)
basis <- abasis
}
if (missing == "a") {
abasis <- matrix (0, nobs, ndim)
abasis [there,] <- basis
abasis [notthere,] <- 1 / ndim
basis <- abasis
}
if (missing == "s") {
abasis <- matrix (0, nobs, ndim + 1)
abasis [there, 1:ndim] <- basis
abasis [notthere, ndim + 1] <- 1
basis <- abasis
}
return (basis)
}
makeIndicator <- function (x) {
return (as.matrix(ifelse(outer(
x, sort(unique(x)), "=="
), 1, 0)))
}
reshape <- function (x, n) {
if (length (x) == 1)
return (rep (x, n))
else
return (x)
}
aline <- function (a) {
abline (0, a[2] / a[1])
}
aperp <- function (a, x) {
abline (x * (sum (a ^ 2) / a[2]),-a[1] / a[2])
}
aproj <- function (a, h, x) {
mu <- (h - sum (a * x)) / (sum (a ^ 2))
return (x + mu * a)
}
stepPlotter <- function (x, y, knots, xlab) {
y <- as.matrix (y)
plot (x,
y[, 1],
type = "n",
xlab = xlab,
ylab = "Transform")
nknots <- length (knots)
knots <- c(min(x) - 1, knots, max(x) + 1)
for (i in 1:(nknots + 1)) {
ind <- which ((x >= knots [i]) & (x < knots[i + 1]))
lev <- median (y [ind, 1])
lines (rbind (c(knots[i], lev), c (knots[i + 1], lev)), col = "RED", lwd = 3)
if (ncol (y) == 2) {
lev <- median (y [ind, 2])
lines (rbind (c(knots[i], lev), c (knots[i + 1], lev)), col = "BLUE", lwd = 3)
}
}
}
starPlotter <- function (x, y, main = "") {
plot(
x,
xlab = "dimension 1",
ylab = "dimension 2",
col = "RED",
cex = .5,
main = main
)
points(y, col = "BLUE", cex = .5)
for (i in 1:nrow(x))
lines (rbind (x[i, ], y[i, ]))
}
regressionPlotter <-
function (table,
x,
y,
xname = "Columns",
yname = "Rows",
main = "",
lines = TRUE,
cex = 1.0,
ticks = "n") {
if (ticks != "n") {
ticks <- NULL
}
nr <- nrow (table)
nc <- ncol (table)
sr <- rowSums (table)
sc <- colSums (table)
rc <- sum (table)
x <- x - sum (sr * x) / rc
y <- y - sum (sc * y) / rc
x <- x / sqrt (sum (sr * (x ^ 2)) / rc)
y <- y / sqrt (sum (sc * (y ^ 2)) / rc)
ar <- drop ((table %*% y) / sr)
ac <- drop ((x %*% table) / sc)
plot (
0,
xlim = c (min(y), max(y)),
ylim = c (min(x), max(x)),
xlab = xname,
ylab = yname,
main = main,
xaxt = ticks,
yaxt = ticks,
type = "n"
)
if (lines) {
for (i in 1:nr)
abline (h = x[i])
for (j in 1:nc)
abline (v = y[j])
}
for (i in 1:nr) {
for (j in 1:nc) {
text(y[j],
x[nr - i + 1],
as.character(table[i, j]),
cex = cex,
col = "RED")
}
}
lines (y, ac, col = "BLUE")
lines (ar, x, col = "BLUE")
}
corList <- function (x) {
m <- length (x)
n <- nrow (x[[1]])
h <- matrix (0, n, 0)
for (i in 1:m) {
h <- cbind (h, x[[i]])
}
return (cor (h))
}
preCorals <- function (x) {
n <- sum (x)
r <- nrow (x)
s <- ncol (x)
v <- numeric (0)
for (i in 1:r)
for (j in 1:s)
v <- c(v, rep(c(i, j), x[i, j]))
return (matrix (v, n, 2, byrow = TRUE))
}
postCorals <- function (ff, x) {
y <- matrix(0, max(ff), ncol (x))
for (i in 1:nrow (x))
y[ff[i],] <- x[i,]
return (y)
}
preCoranals <- function (x, y) {
n <- sum (x)
m <- ncol (y)
r <- nrow (x)
s <- ncol (x)
v <- numeric (0)
for (i in 1:r)
for (j in 1:s)
v <- c(v, rep(c(y[i,], j), x[i, j]))
return (matrix (v, n, m + 1, byrow = TRUE))
}
mprint <- function (x, d = 2, w = 5) {
print (noquote (formatC (
x, di = d, wi = w, fo = "f"
)))
}
burtTable <- function (gifi) {
nsets <- length (gifi)
nobs <- length(gifi[[1]][[1]]$data)
hh <- matrix (0, nobs, 0)
hl <- list ()
for (i in 1:nsets) {
gifiSet <- gifi[[i]]
nvars <- length (gifiSet)
hi <- matrix(0, nobs, 0)
for (j in 1:nvars) {
gifiVariable <- gifiSet[[j]]
hi <- cbind (hi, gifiVariable$basis)
}
hl <- c (hl, list (crossprod (hi)))
hh <- cbind (hh, hi)
}
return (list (cc = crossprod (hh), dd = directSum (hl)))
}
interactiveCoding <- function (data) {
cmin <- apply (data, 2, min)
cmax <- apply (data, 2, max)
if (!all(cmin == 1))
stop ("data must be start at 1")
nobs <- nrow(data)
h <- numeric(0)
for (i in 1:nobs)
h <- c(h, decode (data[i, ], cmax))
return (h)
}
makeColumnProduct <- function (x) {
makeTwoColumnProduct <- function (a, b) {
n <- nrow (a)
ma <- ncol (a)
mb <- ncol (b)
ab <- matrix (0, n, ma * mb)
k <- 1
for (i in 1:ma) {
for (j in 1:mb) {
ab[, k] <- a[, i] * b[, j]
k <- k + 1
}
}
return (ab)
}
if (!is.list(x)) {
x <- list (x)
}
m <- length (x)
z <- matrix (1, nrow(x[[1]]), 1)
for (k in 1:m)
z <- makeTwoColumnProduct (z, x[[k]])
return (z)
}
profileFrequencies <- function (data) {
h <- interactiveCoding (data)
cmax <- apply (data, 2, max)
u <- unique (h)
m <- length (u)
g <- ifelse (outer (h, u, "=="), 1, 0)
n <- colSums (g)
h <- matrix (0, m, ncol (data))
for (j in 1:m)
h[j, ] <- encode (u[j], cmax)
return (list (h = h, n = n))
}
directSum <- function (x) {
m <- length (x)
nr <- sum (sapply (x, nrow))
nc <- sum (sapply (x, ncol))
z <- matrix (0, nr, nc)
kr <- 0
kc <- 0
for (i in 1:m) {
ir <- nrow (x[[i]])
ic <- ncol (x[[i]])
z[kr + (1:ir), kc + (1:ic)] <- x[[i]]
kr <- kr + ir
kc <- kc + ic
}
return (z)
}
17.2 C Code
17.2.1 Splines
double bs (int nknots, int nspline, int degree, double x, double * knots);
int mindex (int i, int j, int nrow);
void splinebasis (int *d, int *n, int *m, double * x, double * knots, double * basis) {
int mm = *m, dd = *d, nn = *n;
int k = mm - dd - 1, i , j, ir, jr;
for (i = 0; i < nn; i++) {
ir = i + 1;
if (x[i] == knots[mm - 1]) {
basis [mindex (ir, k, nn) - 1] = 1.0;
for (j = 0; j < (k - 1); j++) {
jr = j + 1;
basis [mindex (ir, jr, nn) - 1] = 0.0;
}
} else {
for (j = 0; j < k ; j++) {
jr = j + 1;
basis [mindex (ir, jr, nn) - 1] = bs (mm, jr, dd + 1, x[i], knots);
}
}
}
}
int mindex (int i, int j, int nrow) {
return (j - 1) * nrow + i;
}
double bs (int nknots, int nspline, int updegree, double x, double * knots) {
double y, y1, y2, temp1, temp2;
if (updegree == 1) {
if ((x >= knots[nspline - 1]) && (x < knots[nspline]))
y = 1.0;
else
y = 0.0;
}
else {
temp1 = 0.0;
if ((knots[nspline + updegree - 2] - knots[nspline - 1]) > 0)
temp1 = (x - knots[nspline - 1]) / (knots[nspline + updegree - 2] - knots[nspline - 1]);
temp2 = 0.0;
if ((knots[nspline + updegree - 1] - knots[nspline]) > 0)
temp2 = (knots[nspline + updegree - 1] - x) / (knots[nspline + updegree - 1] - knots[nspline]);
y1 = bs(nknots, nspline, updegree - 1, x, knots);
y2 = bs(nknots, nspline + 1, updegree - 1, x, knots);
y = temp1 * y1 + temp2 * y2;
}
return y;
}
17.2.2 Gram-Schmidt
#include <math.h>
#define MINDEX(i, j, n) (((j)-1) * (n) + (i)-1)
void gsC(double *, double *, int *, int *, int *, int *, double *);
void gsC(double *x, double *r, int *n, int *m, int *rank, int *pivot,
double *eps) {
int i, j, ip, nn = *n, mm = *m, rk = *m, jwork = 1;
double s = 0.0, p;
for (j = 1; j <= mm; j++) {
pivot[j - 1] = j;
}
while (jwork <= rk) {
for (j = 1; j < jwork; j++) {
s = 0.0;
for (i = 1; i <= nn; i++) {
s += x[MINDEX(i, jwork, nn)] * x[MINDEX(i, j, nn)];
}
r[MINDEX(j, jwork, mm)] = s;
for (i = 1; i <= nn; i++) {
x[MINDEX(i, jwork, nn)] -= s * x[MINDEX(i, j, nn)];
}
}
s = 0.0;
for (i = 1; i <= nn; i++) {
s += x[MINDEX(i, jwork, nn)] * x[MINDEX(i, jwork, nn)];
}
if (s > *eps) {
s = sqrt(s);
r[MINDEX(jwork, jwork, mm)] = s;
for (i = 1; i <= nn; i++) {
x[MINDEX(i, jwork, nn)] /= s;
}
jwork += 1;
}
if (s <= *eps) {
ip = pivot [rk - 1];
pivot[rk - 1] = pivot[jwork - 1];
pivot[jwork - 1] = ip;
for (i = 1; i <= nn; i++) {
p = x[MINDEX(i, rk, nn)];
x[MINDEX(i, rk, nn)] = x[MINDEX(i, jwork, nn)];
x[MINDEX(i, jwork, nn)] = p;
}
for (j = 1; j <= mm; j++) {
p = r[MINDEX(j, rk, mm)];
r[MINDEX(j, rk, mm)] = r[MINDEX(j, jwork, mm)];
r[MINDEX(j, jwork, mm)] = p;
}
rk -= 1;
}
}
*rank = rk;
}
17.2.3 Coding
#include <R.h>
#include <Rinternals.h>
SEXP DECODE( SEXP, SEXP );
SEXP ENCODE( SEXP, SEXP );
SEXP
DECODE( SEXP cell, SEXP dims )
{
int aux = 1, n = length(dims);
SEXP ind;
PROTECT( ind = allocVector( INTSXP, 1 ) );
INTEGER( ind )[0] = 1;
for( int i = 0; i < n; i++ ) {
INTEGER( ind )[0] += aux * ( INTEGER( cell )[i] - 1 );
aux *= INTEGER(dims)[i];
}
UNPROTECT( 1 );
return (ind);
}
SEXP
ENCODE( SEXP ind, SEXP dims )
{
int n = length(dims), aux = INTEGER(ind)[0], pdim = 1;
SEXP cell;
PROTECT( cell = allocVector( INTSXP, n ) );
for ( int i = 0; i < n - 1; i++ )
pdim *= INTEGER( dims )[i];
for ( int i = n - 1; i > 0; i-- ){
INTEGER( cell )[i] = ( aux - 1 ) / pdim;
aux -= pdim * INTEGER( cell )[i];
pdim /= INTEGER( dims )[i - 1];
INTEGER( cell )[i] += 1;
}
INTEGER( cell )[0] = aux;
UNPROTECT( 1 );
return cell;
}