Nothing
summary.formula <-
function(formula, data=NULL, subset=NULL, na.action=NULL,
fun=NULL,
method=c('response','reverse','cross'),
overall=method == 'response'|method == 'cross',
continuous=10, na.rm=TRUE, na.include=method != 'reverse',
g=4, quant = c(0.025, 0.05, 0.125, 0.25, 0.375, 0.5, 0.625,
0.75, 0.875, 0.95, 0.975),
nmin=if(method == 'reverse') 100 else 0,
test=FALSE,
conTest=conTestkw,
catTest=catTestchisq,
ordTest=ordTestpo,
...)
{
call <- match.call()
missmethod <- missing(method)
method <- match.arg(method)
## Multiple left hand side variables -> automatically call summaryM
if(grepl('.*\\+.*~', paste(deparse(formula), collapse='')))
return(summaryM(formula, data=data, subset=subset,
na.action=na.action, overall=overall,
continuous=continuous, na.include=na.include,
quant=quant, nmin=nmin, test=test,
conTest=conTest, catTest=catTest, ordTest=ordTest))
X <- match.call(expand.dots=FALSE)
X$fun <- X$method <- X$na.rm <- X$na.include <- X$g <-
X$overall <- X$continuous <- X$quant <- X$nmin <- X$test <-
X$conTest <- X$catTest <- X$... <- NULL
if(missing(na.action))
X$na.action <- na.retain
Terms <- if(missing(data)) terms(formula,'stratify')
else terms(formula,'stratify',data=data)
X$formula <- Terms
X[[1]] <- as.name("model.frame")
X <- eval(X, sys.parent())
Terms <- attr(X,"terms")
resp <- attr(Terms,"response")
if(resp == 0 && missmethod)
method <- 'reverse'
if(test && method != 'reverse')
stop('test=TRUE only allowed for method="reverse"')
if(method != 'reverse' && resp != 1)
stop("must have a variable on the left hand side of the formula")
nact <- attr(X, "na.action")
nvar <- ncol(X)-1
strat <- attr(Terms,'specials')$stratify
getlab <- function(x, default)
{
lab <- attr(x, 'label')
if(!length(lab) || lab == '') default else lab
}
if(length(strat)) {
if(method != 'response')
stop('stratify only allowed for method="response"')
sRequire('survival')
temp <- survival::untangle.specials(Terms,'stratify')
strat.name <- var.inner(Terms)[temp$terms]
strat <- if(length(temp$vars) == 1) as.factor(X[[temp$vars]])
else stratify(X[,temp$vars])
strat.label <- getlab(X[,temp$vars[1]], strat.name)
X[[temp$vars]] <- NULL # remove strata factors
} else {
strat <- factor(rep('',nrow(X)))
strat.name <- strat.label <- ''
}
nstrat <- length(levels(strat))
if(resp>0) {
Y <- X[[resp]]
yname <- as.character(attr(Terms,'variables'))[2]
ylabel <- getlab(Y, yname)
if(!is.matrix(Y))
Y <- matrix(Y, dimnames=list(names(Y),yname))
} else {
yname <- ylabel <- NULL
}
if(method != 'reverse') {
if(!length(fun)) { # was missing(fun) 25May01
fun <- function(y) apply(y, 2, mean)
uy <- unique(Y[!is.na(Y)]) # fixed 16Mar96
r <- range(uy, na.rm=TRUE)
funlab <- if(length(uy) == 2 && r[1] == 0 & r[2] == 1) "Fraction"
else "Mean"
funlab <- paste(funlab, 'of', yname)
} else if(is.character(fun) && fun == '%') {
fun <- function(y)
{
stats <- 100*apply(y, 2, mean)
names(stats) <- paste(dimnames(y)[[2]],'%')
stats
}
funlab <- paste('% of', yname)
}
## Compute number of descriptive statistics per cell
s <-
if(inherits(Y,'Surv'))
as.vector((1 * is.na(unclass(Y))) %*% rep(1, ncol(Y)) > 0)
else
((if(is.character(Y)) Y == ''|Y == 'NA'
else is.na(Y)) %*%
rep(1,ncol(Y))) > 0
stats <- if(length(dim(Y))) fun(Y[!s,,drop=FALSE])
else fun(Y[!s])
nstats <- length(stats)
name.stats <-
if(length(dn <- dimnames(stats)) == 2)
as.vector(outer(dn[[1]],dn[[2]],FUN=function(a,b)paste(b,a)))
else
names(stats)
if(length(fun)) {
if(length(de <- deparse(fun)) == 2) {
de <- as.list(fun)
de <- as.character(de[[length(de)]])
funlab <- if(de[1] == 'apply') de[length(de)]
else de[1]
## 2nd case is for simple function(x)mean(x) function
} else funlab <- as.character(substitute(fun))
}
if(funlab[1] == '')
funlab <- yname
if(length(name.stats) == 0) {
name.stats <- if(nstats == 1) yname
else paste0(yname , 1 : nstats)
}
}
if(method == 'response') {
X[[resp]] <- NULL # remove response var
s <-
if(!na.rm) FALSE
else if(inherits(Y,'Surv'))
as.vector((1 * is.na(unclass(Y))) %*% rep(1, ncol(Y)) > 0)
else
((if(is.character(Y)) Y == ''|Y == 'NA'
else is.na(Y)) %*%
rep(1,ncol(Y))) > 0
nmissy <- sum(s)
if(nmissy) {
X <- X[!s,,drop=FALSE]
Y <- Y[!s,,drop=FALSE]
strat <- strat[!s]
}
##Compute total number of columns, counting n
nc <- nstrat*(1+nstats)
colname <- rep(c('N',name.stats),nstrat)
rowname <- vname <- vlabel <- vunits <- res <- NULL
dm <- dim(X)
nx <- dm[2]
n <- dm[1]
nlevels <- integer(nx)
labels <- character(nx)
units <- labels
i <- 0
nams <- c(names(X), if(overall)'Overall')
for(v in nams) {
i <- i+1
x <- if(v == 'Overall') factor(rep('',n))
else X[[v]]
if(inherits(x,'mChoice')) x <- as.numeric(x)
labels[i] <- getlab(x, nams[i])
units[i] <- if(length(l <- attr(x,'units'))) l
else ''
if(!(ismc <- is.matrix(x))) {
s <- is.na(x)
if(!is.factor(x)) {
xu <- unique(x[!s]);
lu <- length(xu)
x <- if(lu < continuous) {
r <- range(xu)
if(lu == 2 && r[1] == 0 && r[2] == 1)
factor(x,labels=c('No','Yes'))
else
factor(x)
} else cut2(x, g=g, ...)
}
if(na.include && any(s)) {
x <- na.include(x)
levels(x)[is.na(levels(x))] <- 'NA'
## R 1.5 and later has NA as level not 'NA', satisfies is.na
}
xlev <- levels(x)
if(nmin > 0) {
nn <- table(x);
xlev <- names(nn)[nn >= nmin]
}
} else {
xlev <- dimnames(x)[[2]]
if(!length(xlev))
stop('matrix variables must have column dimnames')
if(!is.logical(x)) {
if(is.numeric(x))
x <- x == 1
else {
x <- structure(casefold(x),dim=dim(x))
x <- x == 'present' | x == 'yes'
}
}
if(nmin > 0) {
nn <- apply(x, 2, sum, na.rm=TRUE)
xlev <- xlev[nn >= nmin]
}
}
nlevels[i] <- length(xlev)
for(lx in xlev) {
r <- NULL
for(js in levels(strat)) {
j <- if(ismc) strat == js & x[,lx]
else strat == js & x == lx
if(!na.include)
j[is.na(j)] <- FALSE
nj <- sum(j)
f <-
if(nj) {
statz <- unlist(fun(Y[j,,drop=FALSE]))
## 23apr03; had just let matrix replicate to fill
## Thanks: Derek Eder <derek.eder@neuro.gu.se>
if(length(statz) != nstats)
stop(paste('fun for stratum',lx,js,'did not return',
nstats, 'statistics'))
matrix(statz, ncol=nstats, byrow=TRUE)
} else rep(NA,nstats)
r <- c(r, nj, f)
}
res <- rbind(res, r)
}
rowname <- c(rowname, xlev)
bl <- rep('',length(xlev)-1)
vname <- c(vname,v,bl)
vlabel <- c(vlabel,labels[i],bl)
vunits <- c(vunits,units[i],bl)
}
rowname[rowname == 'NA'] <- 'Missing'
dimnames(res) <- list(rowname,colname)
at <- list(formula=formula, call=call, n=n, nmiss=nmissy, yname=yname,
ylabel=ylabel,
ycolname=if(length(d<-dimnames(Y)[[2]]))d else yname,
funlab=funlab,
vname=vname, vlabel=vlabel, nlevels=nlevels,
labels=labels, units=units, vunits=vunits,
strat.name=strat.name, strat.label=strat.label,
strat.levels=levels(strat))
attributes(res) <- c(attributes(res), at)
attr(res,'class') <- 'summary.formula.response'
return(res)
}
if(method == 'reverse') {
quants <- unique(c(quant, 0.025, 0.05, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 0.95, 0.975))
if(resp) {
group <- as.factor(X[[resp]])[,drop=TRUE]
group.freq <- table(group)
group.freq <- group.freq[group.freq>0]
if(overall)
group.freq <- c(group.freq, Combined=sum(group.freq))
} else {
group <- rep(0,nrow(X))
group.freq <- NULL
}
nv <- ncol(X)-resp
n <- integer(nv)
type <- n
nams <- names(X)
comp <- dat <- vector("list",nv)
names(comp) <- names(dat) <- if(resp)nams[-1]
else nams
labels <- Units <- vector("character",nv)
if(test) {
testresults <- vector('list', nv)
names(testresults) <- names(comp)
}
for(i in 1:nv) {
w <- X[[resp+i]]
if(length(attr(w, "label")))
labels[i] <- attr(w, "label")
if(length(attr(w, 'units')))
Units[i] <- attr(w, 'units')
if(!inherits(w, 'mChoice')) {
if(!is.factor(w) && !is.logical(w) &&
length(unique(w[! is.na(w)])) < continuous)
w <- as.factor(w)
s <- !is.na(w)
if(na.include && !all(s) && length(levels(w))) {
w <- na.include(w)
levels(w)[is.na(levels(w))] <- 'NA'
s <- rep(TRUE, length(s))
}
n[i] <- sum(s)
w <- w[s]
g <- group[s, drop=TRUE]
if(is.factor(w) || is.logical(w)) {
tab <- table(w, g)
if(test) {
if(is.ordered(w))
testresults[[i]] <- ordTest(g, w)
else
testresults[[i]] <- catTest(tab)
}
if(nrow(tab) == 1) { # 7sep02
b <- casefold(dimnames(tab)[[1]],upper=TRUE)
pres <- c('1','Y','YES','PRESENT')
abse <- c('0','N','NO', 'ABSENT')
jj <- match(b, pres, nomatch=0)
if(jj > 0)
bc <- abse[jj]
else {
jj <- match(b, abse, nomatch=0)
if(jj > 0) bc <- pres[jj]
}
if(jj) {
tab <- rbind(tab, rep(0, ncol(tab)))
dimnames(tab)[[1]][2] <- bc
}
}
if(overall)
tab <- cbind(tab, Combined=apply(tab,1,sum))
comp[[i]] <- tab
type[i] <- 1
} else {
sfn <- function(x, quant)
{
o <- options('digits')
options(digits=15)
## so won't lose precision in quantile names
on.exit(options(o))
c(quantile(x,quant), Mean=mean(x), SD=sqrt(var(x)))
}
qu <- tapply(w, g, sfn, simplify=TRUE, quants)
if(test)
testresults[[i]] <- conTest(g, w)
if(overall)
qu$Combined <- sfn(w, quants)
comp[[i]] <- matrix(unlist(qu),ncol=length(quants)+2,byrow=TRUE,
dimnames=list(names(qu),
c(format(quants),'Mean','SD')))
if(any(group.freq <= nmin))
dat[[i]] <-
lapply(split(w,g),nmin=nmin,
function(x,nmin)
if(length(x) <= nmin)x
else NULL)
type[i] <- 2
}
} else {
w <- as.numeric(w) == 1 ## multiple choice variables
n[i] <- nrow(w)
g <- as.factor(group)
ncat <- ncol(w)
tab <- matrix(NA, nrow=ncat, ncol=length(levels(g)),
dimnames=list(dimnames(w)[[2]], levels(g)))
if(test) {
pval <- numeric(ncat)
names(pval) <- dimnames(w)[[2]]
d.f. <- stat <- pval
}
for(j in 1:ncat) {
tab[j,] <- tapply(w[,j], g, sum, simplify=TRUE, na.rm=TRUE)
if(test) {
tabj <- rbind(table(g) - tab[j, ], tab[j, ])
st <- catTest(tabj)
pval[j] <- st$P
stat[j] <- st$stat
d.f.[j] <- st$df
}
}
if(test)
testresults[[i]] <- list(P = pval,
stat = stat,
df = d.f.,
testname = st$testname,
statname = st$statname,
namefun = st$namefun,
latexstat = st$latexstat,
plotmathstat = st$plotmathstat)
if(overall)
tab <- cbind(tab, Combined=apply(tab,1,sum))
comp[[i]] <- tab
type[i] <- 3
}
}
labels <- ifelse(nchar(labels), labels, names(comp))
return(structure(list(stats=comp, type=type,
group.name=if(resp)nams[1]
else NULL,
group.label=ylabel,
group.freq=group.freq,
labels=labels, units=Units,
quant=quant, data=dat,
N=sum(!is.na(group)), n=n,
testresults=if(test)testresults
else NULL,
call=call, formula=formula),
class="summary.formula.reverse"))
}
if(method == 'cross') {
X[[resp]] <- NULL
Levels <- vector("list",nvar)
nams <- names(X)
names(Levels) <- names(X)
labels <- character(nvar)
for(i in 1:nvar) {
xi <- X[[i]]
if(inherits(xi,'mChoice'))
xi <- factor(format(xi))
else if(is.matrix(xi) && ncol(xi) > 1)
stop('matrix variables not allowed for method="cross"')
labels[i] <- getlab(xi, nams[i])
if(is.factor(xi))
xi <- xi[,drop=TRUE]
if(!is.factor(xi) && length(unique(xi[!is.na(xi)]))>=continuous)
xi <- cut2(xi, g=g, ...)
X[[i]] <- na.include(as.factor(xi))
levels(X[[i]])[is.na(levels(X[[i]]))] <- 'NA'
Levels[[i]] <- c(levels(X[[i]]),if(overall)"ALL")
}
##Make a data frame with all combinations of values (including those
##that don't exist in the data, since trellis needs them)
df <- expand.grid(Levels)
nl <- nrow(df)
N <- Missing <- integer(nl)
na <- is.na(Y %*% rep(1,ncol(Y)))
S <- matrix(NA, nrow=nl, ncol=nstats, dimnames=list(NULL,name.stats))
chk <- function(z, nstats)
{
if(length(z) != nstats)
stop(paste('fun did not return',nstats,
'statistics for a stratum'))
z
}
if(nvar == 1) {
df1 <- as.character(df[[1]]); x1 <- X[[1]]
for(i in 1:nl) {
s <- df1[i] == 'ALL' | x1 == df1[i]
w <- if(na.rm) s & !na else s
N[i] <- sum(w)
Missing[i] <- sum(na[s])
S[i,] <- if(any(w))chk(fun(Y[w,,drop=FALSE]),nstats)
else rep(NA,nstats)
}
} else if(nvar == 2) {
df1 <- as.character(df[[1]]);
df2 <- as.character(df[[2]])
x1 <- X[[1]];
x2 <- X[[2]]
for(i in 1:nl) {
s <- (df1[i] == 'ALL' | x1 == df1[i]) & (df2[i] == 'ALL' | x2 == df2[i])
w <- if(na.rm) s & !na
else s
N[i] <- sum(w)
Missing[i] <- sum(na[s])
S[i,] <- if(any(w))chk(fun(Y[w,,drop=FALSE]),nstats)
else rep(NA,nstats)
}
} else if(nvar == 3) {
df1 <- as.character(df[[1]]);
df2 <- as.character(df[[2]])
df3 <- as.character(df[[3]])
x1 <- X[[1]];
x2 <- X[[2]];
x3 <- X[[3]]
for(i in 1:nl) {
s <- (df1[i] == 'ALL' | x1 == df1[i]) & (df2[i] == 'ALL' | x2 == df2[i]) &
(df3[i] == 'ALL' | x3 == df3[i])
w <- if(na.rm) s & !na
else s
N[i] <- sum(w)
Missing[i] <- sum(na[s])
S[i,] <- if(any(w))chk(fun(Y[w,,drop=FALSE]),nstats)
else rep(NA,nstats)
}
} else stop('no more than 3 independent variables allowed')
lab <- names(df)
lab2 <- if(length(lab)>1) paste(lab,collapse=", ")
else lab
heading <- paste(funlab,"by",lab2)
S <- S[,,drop=TRUE]
attr(S,"label") <- yname #funlab
df$S <- S
df$N <- N
df$Missing <- Missing
a <- list(heading=heading,byvarnames=lab2,Levels=Levels,labels=labels,
na.action=nact,formula=formula,call=call,yname=yname,ylabel=ylabel,
class=c("summary.formula.cross","data.frame"))
attributes(df) <- c(attributes(df), a)
df
}
}
##The following makes formula(object) work (using especially for update())
formula.summary.formula.cross <- function(x, ...) attr(x,'formula')
na.retain <- function(d) d
print.summary.formula.response <-
function(x,
vnames=c('labels','names'), prUnits=TRUE,
abbreviate.dimnames=FALSE,
prefix.width, min.colwidth,
formatArgs=NULL, markdown=FALSE, ...)
{
stats <- x
stats <- unclass(stats)
vnames <- match.arg(vnames)
ul <- vnames == 'labels'
at <- attributes(stats)
ns <- length(at$strat.levels)
vlabels <- at$labels
if(prUnits) {
atu <- gsub('*', ' ', at$units, fixed=TRUE)
vlabels <- ifelse(atu == '',vlabels,
paste0(vlabels,' [',atu,']'))
}
cap <- paste(at$ylabel,
if(ns>1)
paste0(' by',
if(ul) at$strat.label
else at$strat.name),
' N=',at$n,
if(at$nmiss) paste0(', ',at$nmiss,' Missing'))
if(! markdown) cat(cap, '\n\n')
d <- dim(stats)
nr <- length(at$nlevels)
vlab <- if(ul) vlabels[vlabels != '']
else at$vname[at$vname != '']
z <- matrix('',nrow=nr,ncol=1+d[2],dimnames=list(vlab,NULL))
dz <- dimnames(stats)[[1]]
cstats <- matrix('',nrow=d[1],ncol=d[2])
for(j in 1:d[2]) {
ww <- c(list(stats[,j]), formatArgs)
cstats[,j] <- do.call('format', ww)
cstats[is.na(stats[,j]),j] <- ''
}
if(markdown) {
if(! requireNamespace("knitr", quietly=TRUE))
stop('markdown=TRUE requires the knitr package to be installed')
vlab <- if(ul) at$vlabel else at$vname
if(prUnits && any(at$units != ''))
vlab[vlab != ''] <- paste0(vlab[vlab != ''], '[', at$units, ']')
if(vlab[length(vlab)] == 'Overall')
vlab[length(vlab)] <- '**Overall**'
z <- cbind(vlab, rownames(x), cstats)
colnames(z) <- c('', '', colnames(stats))
return(knitr::kable(z, align=c('l', 'l', rep('r', ncol(cstats))),
caption=cap))
}
is <- 1
for(i in 1:nr) {
ie <- is+at$nlevels[i]-1
z[i,1] <- paste(dz[is:ie],collapse='\n')
for(j in 1:d[2]) z[i,j+1] <- paste(cstats[is:ie,j],collapse='\n')
is <- ie+1
}
if(missing(prefix.width))
prefix.width <- max(nchar(dimnames(z)[[1]]))
if(missing(min.colwidth))
min.colwidth <-
max(min(nchar(cstats)[nchar(cstats)>0]), min(nchar(dimnames(stats)[[2]])))
z <- rbind(c('',dimnames(stats)[[2]]), z)
print.char.matrix(z, col.names=FALSE, ...)
invisible()
}
latex.summary.formula.response <-
function(object,
title=first.word(deparse(substitute(object))), caption,
trios, vnames=c('labels','names'), prn=TRUE, prUnits=TRUE,
rowlabel='', cdec=2,
ncaption=TRUE, ...)
{
stats <- object
if(!prn)
stats <- stats[, dimnames(stats)[[2]] != 'N', drop=FALSE]
title <- title # otherwise problem with lazy evaluation 25May01
stats <- unclass(stats)
at <- attributes(stats)
vnames <- match.arg(vnames)
ul <- vnames == 'labels'
ns <- length(at$strat.levels)
nstat <- ncol(stats)/ns
if(!missing(trios)) {
if(is.logical(trios))
trios <- at$ycolname
ntrio <- length(trios)
if(ntrio*3 + prn != nstat) #allow for N
stop('length of trios must be 1/3 the number of statistics computed')
}
if(missing(caption)) caption <- latexTranslate(at$ylabel)
if(ns>1) caption <- paste(caption,' by', if(ul)at$strat.label else
at$strat.name)
if(ncaption)
caption <- paste0(caption,
'~~~~~N=',at$n,
if(at$nmiss) paste0(',~',at$nmiss,' Missing'))
dm <- dimnames(stats)
dm[[1]] <- latexTranslate(dm[[1]], greek=TRUE)
dm[[2]] <- latexTranslate(dm[[2]], greek=TRUE)
dimnames(stats) <- dm
caption <- sedit(caption, "cbind", "")
vn <- if(ul)at$vlabel
else at$vname
if(prUnits) {
atvu <- gsub('*', ' ', at$vunits, fixed=TRUE)
vn <- ifelse(atvu == '', vn,
paste0(vn,'~\\hfill\\tiny{', atvu, '}'))
}
vn <- latexTranslate(vn, greek=TRUE)
if(missing(trios)) {
cdec <- rep(cdec, length = nstat)
} else {
cdec <- rep(cdec, length = nstat / 3)
}
cdec <- rep(cdec, ns)
isn <- colnames(stats) %in% c('N', 'n')
if(any(isn) && prn) cdec[isn] <- 0
if(missing(trios)) {
cstats <- unclass(stats)
} else {
fmt <- function(z, cdec) ifelse(is.na(z), '', format(round(z, cdec)))
cstats <- list()
k <- m <- 0
for(is in 1 : ns) {
if(prn) {
k <- k + 1
m <- m + 1
cstats[[k]] <- stats[, m] ## N, numeric mode
}
for(j in 1 : ntrio) {
m <- m + 1
k <- k + 1
cstats[[k]] <- paste0('{\\scriptsize ', fmt(stats[,m], cdec[k]), '~}',
fmt(stats[,m + 1], cdec[k]), ' {\\scriptsize ',
fmt(stats[,m + 2], cdec[k]), '}')
m <- m + 2
}
}
names(cstats) <- rep(c(if(prn)'N'
else NULL, trios), ns)
attr(cstats, 'row.names') <- dm[[1]]
attr(cstats,'class') <- 'data.frame'
if(prn)
nstat <- 2 # for n.cgroup below
else
nstat <- 1
}
insert.bottom <-
if(missing(trios))
''
else
'\\noindent {\\scriptsize $a$\\ } $b$ {\\scriptsize $c$\\ } represent the lower quartile $a$, the median $b$, and the upper quartile $c$.'
r <-
if(ns > 1)
latex(cstats, title=title, caption=caption, rowlabel=rowlabel,
n.rgroup=at$nlevels, rgroup=vn[vn != ''],
n.cgroup=rep(nstat,ns), cgroup=at$strat.levels, cdec=cdec,
col.just=rep('c',ncol(cstats)),
rowname=dm[[1]], insert.bottom=insert.bottom, ...)
else
latex(cstats, title=title, caption=caption, rowlabel=rowlabel,
n.rgroup=at$nlevels, rgroup=vn[vn != ''], cdec=cdec,
col.just=rep('c',ncol(cstats)),
rowname=dm[[1]], insert.bottom=insert.bottom, ...)
r
}
plot.summary.formula.response <-
function(x, which = 1,
vnames = c('labels', 'names'), xlim, xlab,
pch = c(16, 1, 2, 17, 15, 3, 4, 5, 0), superposeStrata = TRUE,
dotfont=1, add=FALSE, reset.par=TRUE,
main, subtitles=TRUE, ...)
{
stats <- x
stats <- unclass(stats)
vnames <- match.arg(vnames)
ul <- vnames == 'labels'
at <- attributes(stats)
ns <- length(at$strat.levels)
if(ns>1 && length(which)>1)
stop('cannot have a vector for which if > 1 strata present')
if(ns < 2)
superposeStrata <- FALSE
vn <- if(ul) at$vlabel
else at$vname
Units <- at$vunits
vn <- ifelse(Units == '', vn, paste0(vn, ' [', Units, ']'))
## dotchart2 groups argument may not be an R plotmath expression
vn <- vn[vn != '']
d <- dim(stats)
n <- d[1]
nstat <- d[2]/ns
vnd <- factor(rep(vn, at$nlevels))
dn <- dimnames(stats)
if(missing(xlim))
xlim <- range(stats[,nstat*((1:ns)-1)+1+which],na.rm=TRUE)
if(missing(main))
main <- at$funlab
nw <- length(which)
pch <- rep(pch, length.out=if(superposeStrata)ns else nw)
dotfont <- rep(dotfont, length.out=nw)
opar <- par(no.readonly=TRUE)
if(reset.par)
on.exit(par(opar))
if(superposeStrata) Ns <- apply(stats[,nstat*((1:ns)-1)+1],1,sum)
for(is in 1:ns) {
for(w in 1:nw) {
js <- nstat*(is-1)+1+which[w]
z <- stats[,js]
if(missing(xlab))
xlab <- if(nw>1) dn[[2]][js]
else at$ylabel
dotchart2(z, groups=vnd, xlab=xlab, xlim=xlim,
auxdata=if(superposeStrata) Ns
else stats[,js-which[w]],
auxtitle='N', sort.=FALSE,
pch=pch[if(superposeStrata)is
else w],
dotfont=dotfont[w],
add=add | w>1 | (is > 1 && superposeStrata),
reset.par=FALSE, ...)
if(ns>1 && !superposeStrata)
title(paste(paste(main,if(main != '')' '),at$strat.levels[is]))
else if(main != '') title(main)
if(ns == 1 && subtitles) {
title(sub=paste0('N=', at$n), adj=0, cex=.6)
if(at$nmiss>0)
title(sub=paste0('N missing=', at$nmiss), cex=.6, adj=1)
}
}
}
if(superposeStrata) { ##set up for Key()
Key1 <- function(x=NULL, y=NULL, lev, pch) {
oldpar <- par('usr', 'xpd')
par(usr=c(0,1,0,1),xpd=NA)
on.exit(par(oldpar))
if(is.list(x)) {
y <- x$y;
x <- x$x
}
if(!length(x)) x <- 0
if(!length(y)) y <- 1 ## because of formals()
rlegend(x, y, legend=lev, pch=pch, ...)
invisible()
}
formals(Key1) <- list(x=NULL,y=NULL,lev=at$strat.levels,
pch=pch)
.setKey(Key1)
}
invisible()
}
plot.summary.formula.reverse <-
function(x, vnames = c('labels', 'names'), what = c('proportion','%'),
which = c('both', 'categorical', 'continuous'),
xlim = if(what == 'proportion') c(0,1)
else c(0,100),
xlab = if(what == 'proportion') 'Proportion'
else 'Percentage',
pch = c(16, 1, 2, 17, 15, 3, 4, 5, 0), exclude1 = TRUE,
dotfont = 1, main,
prtest = c('P', 'stat', 'df', 'name'), pdig = 3, eps = 0.001,
conType = c('dot', 'bp', 'raw'), cex.means = 0.5, ...)
{
obj <- x
vnames <- match.arg(vnames)
what <- match.arg(what)
which <- match.arg(which)
conType <- match.arg(conType)
ul <- vnames == 'labels'
if(is.logical(prtest) && ! prtest) prtest <- 'none'
test <- obj$testresults
if(!length(test)) prtest <- 'none'
varNames <- names(obj$stats)
vn <- if(ul) obj$labels
else varNames
Units <- obj$units
nw <- if(lg <- length(obj$group.freq)) lg
else 1
gnames <- names(obj$group.freq)
if(missing(main))
main <- if(nw == 1)''
else
paste(if(what == 'proportion')'Proportions'
else 'Percentages','Stratified by',
obj$group.label)
pch <- rep(pch, length.out=nw)
dotfont <- rep(dotfont, length.out=nw)
lab <- vnd <- z <- nmiss <- vnamd <- NULL
type <- obj$type; n <- obj$n
opar <- par()
on.exit(setParNro(opar))
npages <- 0
if(which != 'continuous' && any(type %in% c(1,3))) {
ftstats <- NULL
for(i in (1:length(type))[type == 1 | type == 3]) {
nam <- vn[i]
tab <- obj$stats[[i]]
if(nw == 1)
tab <- as.matrix(tab)
nr <- nrow(tab)
denom <- if(type[i] == 1) apply(tab, 2, sum)
else obj$group.freq
y <- (if(what == 'proportion') 1
else 100) * sweep(tab, 2, denom, FUN='/')
lev <- dimnames(y)[[1]]
exc <- exclude1 && (nr == 2)
jstart <- if(exc) 2
else 1
## nn <- c(nn, n[i], rep(NA, if(exc) nr-2 else nr-1))
## k <- 0
rl <- casefold(lev)
binary <- type[i] == 1 && exc &&
(all(rl %in% c("0","1"))|all(rl %in% c("false","true"))|
all(rl %in% c("absent","present")))
for(j in jstart:nrow(y)) {
if(nw == 1)
z <- rbind(z, y[j,])
else {
yj <- rep(NA, nw)
names(yj) <- gnames
yj[names(y[j,])] <- y[j,]
z <- rbind(z, yj)
}
lab <- c(lab, if(binary) ''
else lev[j])
vnd <- c(vnd, nam)
vnamd <- c(vnamd, varNames[i])
}
if(any(prtest != 'none')) {
fts <- formatTestStats(test[[varNames[i]]], type[i] == 3,
if(type[i] == 1)1
else 1 : nr,
prtest=prtest,
plotmath=TRUE,
pdig=pdig, eps=eps)
ftstats <- c(ftstats, fts,
if(type[i] == 1 && nr - exc - 1 > 0)
rep(expression(''),
nr - exc - 1))
}
}
dimnames(z) <- list(lab, dimnames(z)[[2]])
for(i in 1 : nw) {
zi <- z[,i]
if(any(prtest == 'none') || i > 1)
dotchart2(zi, groups=vnd, xlab=xlab, xlim=xlim,
sort.=FALSE, pch=pch[i],
dotfont=dotfont[i],
add=i > 1, ...)
else
dotchart2(zi, groups=vnd, auxdata=ftstats,
xlab=xlab, xlim=xlim, sort.=FALSE,
pch=pch[i], dotfont=dotfont[i],
add=i > 1, ...)
}
if(main != '')
title(main)
npages <- npages + 1
setParNro(opar)
## Dummy key if only one column, so won't use another Key from an
## earlier run
if(nw < 2) {
Key1 <- function(...)invisible(NULL)
.setKey(Key1)
} else { ##set up for key() if > 1 column
Key3 <- function(x=NULL, y=NULL, lev, pch) {
oldpar <- par('usr', 'xpd')
par(usr=c(0,1,0,1),xpd=NA)
on.exit(par(oldpar))
if(is.list(x)) {
y <- x$y;
x <- x$x
}
## Even though par('usr') shows 0,1,0,1 after lattice draws
## its plot, it still needs resetting
if(!length(x))
x <- 0
if(!length(y))
y <- 1 ## because of formals()
rlegend(x, y, legend=lev, pch=pch, ...)
invisible()
}
formals(Key3) <- list(x=NULL,y=NULL,lev=names(obj$group.freq),
pch=pch)
.setKey(Key3)
}
}
ncont <- sum(type == 2)
if(which != 'categorical' && ncont) {
mf <- par('mfrow')
if(length(mf) == 0)
mf <- c(1,1)
if(ncont > 1 & max(mf) == 1) {
mf <- if(ncont <= 4)c(2,2)
else if(ncont <= 6)c(2,3)
else if(ncont <= 9)c(3,3)
else c(4,3)
## if(ncont <= 12)c(4,3) else if(ncont <= 16) c(4,4) else c(5,4)
nr <- mf[1]
m <- par('mar')
par(mfrow=mf)
}
npages <- npages + ceiling(sum(type == 2) / prod(mf))
for(i in (1:length(type))[type == 2]) {
nam <- labelPlotmath(vn[i], Units[i])
st <- obj$stats[[i]]
if(nw == 1)
st <- as.matrix(st)
if(conType == 'dot') {
quantile.columns <- dimnames(st)[[2]] %nin% c('Mean','SD')
st <- st[,quantile.columns,drop=FALSE]
xlim <- range(st)
ns <- as.numeric(dimnames(st)[[2]])
l <- 1:length(ns)
q1 <- l[abs(ns-.25) < .001]
med <- l[abs(ns-.5) < .001]
q3 <- l[abs(ns-.75) < .001]
st <- st[,c(q1,med,q3),drop=FALSE]
for(j in 1:3) {
stj <- st[,j]
if(nw == 1)
names(stj) <- ''
dotchart2(stj, xlab=nam, xlim=xlim, sort.=FALSE,
pch=c(91,
if(FALSE)183
else 16,
93)[j],
dotfont=dotfont[1],
add=j > 1, ...)
}
Key2 <- function(x=NULL, y=NULL, quant, ...)
{
quant <- format(quant)
txt <- paste0('(',quant[2],',',quant[3],',',quant[4],
') quantiles shown\nx-axes scaled to (',quant[1],',',
quant[5],') quantiles')
if(length(x)) {
if(is.list(x)) {
y <- x$y;
x <- x$x
}
text(x,y,txt, cex=.8, adj=0, ...)
} else
mtitle(lr=txt, cex.l=.8, line=1, ...)
invisible()
}
formals(Key2) <- list(x=NULL,y=NULL,quant=obj$quant)
.setKey2(Key2)
} else if(conType == 'bp')
bpplt(st, xlab=nam, cex.points=cex.means)
else
stripChart(obj$data[[i]], xlab=nam)
if(all(prtest != 'none')) {
fts <- formatTestStats(test[[varNames[i]]], prtest=prtest,
plotmath=TRUE,
pdig=pdig, eps=eps)
title(fts, line=.5)
}
}
}
invisible(npages)
}
#This version of the stardard dotchart function allows a vector of values
#to be specified (typically cell sizes) that are written to the right
#or horizontal (only) dot charts. New vectors and auxdata and auxgdata and
#a label for auxdata, auxtitle.
#Also added: sort. parameter, to allow suppression of rearrangements of data,
#and added the parameter `add'. Reference lines are always drawn with lwd=1.
#There's also a new parameter, groupfont, which specifies a font number for
#group headings.
#cex.labels is a cex to be used only for category labels. Default is cex.
#Added reset.par - set to T to reset par() after making plot. You will
#need to set reset.par to T for the last call in a sequence.
dotchart2 <-
function(data, labels, groups = NULL, gdata = NA, horizontal = TRUE,
pch = 16,
xlab = "", ylab="", xlim=NULL, auxdata, auxgdata=NULL, auxtitle,
lty = 1,
lines = TRUE, dotsize = .8, cex = par("cex"),
cex.labels = cex, cex.group.labels = cex.labels*1.25, sort.=TRUE,
add=FALSE, dotfont=par('font'),
groupfont=2, reset.par=add, xaxis=TRUE,
width.factor=1.1, lcolor='gray',
leavepar=FALSE, axisat=NULL, axislabels=NULL,
...)
{
if(!add) {
plot.new() ## needed for strwidth
par(new=TRUE)
}
ieaux <- if(missing(auxdata)) FALSE else is.expression(auxdata)
mtextsrt <- function(..., srt=0) mtext(..., las=1)
ndata <- length(data)
if(missing(labels)) {
if(!is.null(names(data)))
labels <- names(data)
else labels <- paste("#", seq(along = ndata))
}
else
labels <- rep(as.character(labels), length = ndata)
if(missing(groups)) {
glabels <- NULL
gdata <- NULL
}
else {
if(!sort.) {
##assume data sorted in groups, but re-number groups
##to be as if groups given in order 1,2,3,...
ug <- unique(as.character(groups))
groups <- factor(as.character(groups),levels=ug)
}
groups <- unclass(groups)
glabels <- levels(groups)
gdata <- rep(gdata, length = length(glabels))
ord <- order(groups, seq(along = groups))
groups <- groups[ord]
data <- data[ord]
labels <- labels[ord]
if(!missing(auxdata)) auxdata <- auxdata[ord]
}
alldat <- c(data, gdata)
if(!missing(auxdata)) {
auxdata <- c(auxdata, auxgdata)
if(!ieaux) auxdata <- format(auxdata)
}
alllab <- paste(c(labels, glabels),'')
## set up margins and user coordinates, draw box
tcex <- par('cex')
tmai <- par("mai")
oldplt <- par("plt")
if(reset.par && !leavepar)
on.exit(par(mai = tmai, cex = tcex))
par(cex = cex)
mxlab <- .1+max(strwidth(labels, units='inches',cex=cex.labels),
if(length(glabels))
strwidth(glabels,units='inches',cex=cex.group.labels))*
width.factor
if(horizontal) {
tmai2 <- tmai[3:4]
if(!missing(auxdata))
tmai2[2] <- .2+width.factor*
max(strwidth(if(ieaux) auxdata else format(auxdata),
units='inches',cex=cex.labels))
if(!leavepar) par(mai = c(tmai[1], mxlab, tmai2))
if(!add)
plot(alldat, seq(along = alldat), type = "n",
ylab = '', axes = FALSE, xlab = '', xlim=xlim, ...)
logax <- par("xaxt") == "l"
}
else {
if(!leavepar) par(mai = c(mxlab, tmai[2:4]))
if(!add)
plot(seq(along = alldat), alldat, type = "n",
xlab = "", axes = FALSE, ylab = '', ...)
logax <- par("yaxt") == "l"
}
tusr <- par("usr")
if(!add && logax) {
if(horizontal)
abline(v = 10^tusr[1:2], h = tusr[3:4])
else abline(v = tusr[1:2], h = 10^tusr[3:4])
}
else if(!add) abline(v = tusr[1:2], h = tusr[3:4])
den <- ndata + 2 * length(glabels) + 1
if(horizontal) {
if(!add && xaxis)
mgp.axis(1, axistitle=xlab, at=axisat, labels=axislabels)
delt <- ( - (tusr[4] - tusr[3]))/den
ypos <- seq(tusr[4], by = delt, length = ndata)
}
else {
if(!add)
mgp.axis(2, axistitle=xlab, at=axisat, labels=axislabels)
delt <- (tusr[2] - tusr[1])/den
ypos <- seq(tusr[1], by = delt, length = ndata)
}
if(!missing(groups)) {
ypos1 <- ypos + 2 * delt *
(if(length(groups)>1) cumsum(c(1, diff(groups) > 0)) else 1)
diff2 <- c(3 * delt, diff(ypos1))
ypos2 <- ypos1[abs(diff2 - 3 * delt) < abs(0.001 * delt)] -
delt
ypos <- c(ypos1, ypos2) - delt
}
##put on labels and data
ypos <- ypos + delt
nongrp <- 1:ndata
if(horizontal) {
xmin <- par('usr')[1]
if(!add && lines)
abline(h = ypos[nongrp], lty = lty, lwd=1, col=lcolor)
points(alldat, ypos, pch = pch, cex = dotsize * cex, font=dotfont, ...)
if(!add && !missing(auxdata)) {
faux <- if(ieaux) auxdata else format(auxdata)
upedge <- par('usr')[4]
outerText(faux, ypos[nongrp], cex=cex.labels)
if(!missing(auxtitle))
outerText(auxtitle,
upedge+strheight(auxtitle,cex=cex.labels)/2,
cex=cex.labels)
}
if(!add) {
labng <- alllab[nongrp]
## Bug in sending character strings to mtext or text containing
## [ or ] - they don't right-justify in S+
bracket <- substring(labng,1,1) == '[' |
substring(labng,nchar(labng),nchar(labng)) == ']'
yposng <- ypos[nongrp]
s <- !bracket
if(!is.na(any(s)) && any(s))
mtextsrt(paste(labng[s],''), 2, 0, at=yposng[s],
srt=0, adj=1, cex=cex.labels)
s <- bracket
if(!is.na(any(s)) && any(s))
text(rep(par('usr')[1],sum(s)),
yposng[s], labng[s], adj=1,
cex=cex.labels, srt=0,xpd=NA)
if(!missing(groups))
mtextsrt(paste(alllab[ - nongrp],''), 2, 0, at = ypos[ - nongrp],
srt = 0, adj = 1, cex = cex.group.labels, font=groupfont)
}
}
else {
if(!add && lines)
abline(v = ypos[nongrp], lty = lty, lwd=1, col=lcolor)
points(ypos, alldat, pch = pch, cex = dotsize * cex, font=dotfont, ...)
if(!add) mtextsrt(alllab[nongrp], 1, 0,
at = ypos[nongrp], srt = 90, adj = 1,
cex = cex.labels)
if(!add && !missing(groups))
mtextsrt(alllab[ - nongrp], 1, 0, at = ypos[ - nongrp],
srt = 90, adj = 1, cex = cex.group.labels, font=groupfont)
}
plt <- par("plt")
if(horizontal) {
frac <- (oldplt[2] - oldplt[1])/(oldplt[2] - plt[1])
umin <- tusr[2] - (tusr[2] - tusr[1]) * frac
tusr <- c(umin, tusr[2:4])
}
else {
frac <- (oldplt[4] - oldplt[3])/(oldplt[4] - plt[3])
umin <- tusr[4] - (tusr[4] - tusr[3]) * frac
tusr <- c(tusr[1:2], umin, tusr[4])
}
invisible()
}
print.summary.formula.reverse <-
function(x, digits, prn=any(n != N), pctdig=0,
what=c('%', 'proportion'),
npct=c('numerator','both','denominator','none'),
exclude1=TRUE, vnames=c("labels","names"), prUnits=TRUE,
sep="/", abbreviate.dimnames=FALSE,
prefix.width=max(nchar(lab)),
min.colwidth, formatArgs=NULL, round=NULL,
prtest=c('P','stat','df','name'), prmsd=FALSE, long=FALSE,
pdig=3, eps=0.001, ...)
{
npct <- match.arg(npct)
vnames <- match.arg(vnames)
what <- match.arg(what)
if(is.logical(prtest) && !prtest)
prtest <- 'none'
stats <- x$stats
nv <- length(stats)
cstats <- lab <- character(0)
nn <- integer(0)
type <- x$type
n <- x$n
N <- x$N
nams <- names(stats)
labels <- x$labels
Units <- x$units
test <- x$testresults
if(! length(test)) prtest <- 'none'
nw <- if(lg <- length(x$group.freq)) lg else 1
gnames <- names(x$group.freq)
if(!missing(digits)) {
oldopt <- options('digits')
options(digits=digits)
on.exit(options(oldopt))
}
cstats <- NULL
for(i in 1:nv) {
nn <- c(nn, n[i])
nam <- if(vnames == "names") nams[i] else labels[i]
if(prUnits && nchar(Units[i]))
nam <- paste0(nam,' [', gsub('*',' ', Units[i], fixed=TRUE),']')
tr <- if(length(test) && all(prtest != 'none')) test[[nams[i]]]
else NULL
if(type[i] == 1 || type[i] == 3) {
cs <- formatCats(stats[[i]], nam, tr, type[i],
if(length(x$group.freq)) x$group.freq else x$n[i],
what, npct, pctdig, exclude1, long, prtest,
pdig=pdig, eps=eps)
nn <- c(nn, rep(NA, nrow(cs) - 1))
} else cs <- formatCons(stats[[i]], nam, tr, x$group.freq, prmsd,
sep, formatArgs, round, prtest,
pdig=pdig, eps=eps)
cstats <- rbind(cstats, cs)
}
lab <- dimnames(cstats)[[1]]
gl <- names(x$group.freq)
gl <- if(length(gl)) paste0(gl," \n(N=",x$group.freq,")")
else ""
if(length(test) && ! all(prtest == 'none'))
gl <- c(gl,
if(length(prtest) == 1 && prtest != 'stat')
if(prtest == 'P')'P-value'
else prtest
else ' Test\nStatistic')
nc <- nchar(cstats)
spaces <- substring(" ",
1, (max(nc)-nc+1)/2) # center strings
dc <- dim(cstats)
cstats <- paste0(spaces, cstats)
dim(cstats) <- dc
if(prn) {
cnn <- format(nn)
cnn[is.na(nn)] <- ''
cstats <- cbind(cnn, cstats)
gl <- c('N', gl)
}
cstats <- rbind(gl, cstats)
dimnames(cstats) <- list(c('',lab), NULL)
cat("\n\nDescriptive Statistics",
if(length(x$group.label))
paste(" by",x$group.label)
else
paste0(" (N=",x$N,")"),"\n\n", sep="")
if(missing(min.colwidth))
min.colwidth <- max(min(nchar(gl)),min(nc[nc>0]))
print.char.matrix(cstats, col.names=FALSE,
col.txt.align='left', ...)
invisible(cstats)
}
## Function to format subtable for categorical var, for method='reverse'
formatCats <- function(tab, nam, tr, type, group.freq,
what=c('%', 'proportion'),
npct, pctdig, exclude1, long, prtest,
lang='plain', testUsed=character(0),
npct.size='scriptsize', pdig=3, eps=.001,
footnoteTest=TRUE, dotchart=FALSE, mspecs=markupSpecs)
{
what <- match.arg(what)
gnames <- names(group.freq)
nr <- nrow(tab)
specs <- mspecs[[lang]]
spc <- specs$space
sspc <- if(lang == 'plain') '' else specs$sspace
lspc <- specs$lspace
bold <- specs$bold
frac <- specs$frac
if(lang != 'latex' && ! is.function(npct.size))
npct.size <- function(x) x
else if(! is.function(npct.size)) {
npctsize <- npct.size
npct.size <- function(x) paste0('{\\', npctsize, ' ', x, '}')
}
## If there was a missing column of tab because e.g. the variable was
## always NA for one (or more) of the groups, add columns of NAs
if(ncol(tab) < length(group.freq)) {
tabfull <- matrix(NA, nrow=nr, ncol=length(group.freq),
dimnames=list(dimnames(tab)[[1]], gnames))
tabfull[,dimnames(tab)[[2]]] <- tab
tab <- tabfull
}
denom <- if(type == 1) apply(tab, 2, sum)
else group.freq
pct <- if(ncol(tab) > 1) sweep(tab, 2, denom, FUN='/') else tab / denom
pct <- pct * (if(what == '%') 100 else 1)
cpct <- paste0(format(round(pct, pctdig)),
if(lang == 'latex' && what == '%') '\\%'
else if(what == '%') "%")
denom.rep <- matrix(rep(format(denom), nr), nrow=nr, byrow=TRUE)
if(npct != 'none')
cpct <-
paste(cpct,
switch(npct,
numerator = npct.size(paste0(' (', format(tab), ')')),
denominator = npct.size(paste0(' of ', denom.rep)),
both = npct.size(paste0(frac(format(tab),
denom.rep))),
slash = npct.size(paste0(spc, format(tab),
sspc, '/', sspc, denom.rep))
) )
if(lang == 'latex') cpct <- sedit(cpct, ' ', spc)
dim(cpct) <- dim(pct)
dimnames(cpct) <- dimnames(pct)
cpct[is.na(pct)] <- ""
lev <- dimnames(pct)[[1]]
exc <- exclude1 && (nr == 2) && (type == 1)
rl <- casefold(dimnames(pct)[[1]])
binary <- type == 1 && exc &&
(all(rl %in% c("0","1")) | all(rl %in% c("false","true")) |
all(rl %in% c("absent","present")))
if(binary) long <- FALSE
jstart <- if(exc) 2 else 1
nw <- if(lg <- length(group.freq)) lg else 1
lab <- if(binary) nam
else if(long) c(nam, paste(spc, spc, lev[jstart : nr]))
else c(paste(nam, ':', lev[jstart]),
if(nr > jstart) paste(lspc, lev[(jstart + 1) : nr]))
cs <- matrix('', nrow=long + (if(exc) nr - 1
else nr),
ncol = nw + (length(tr) > 0),
dimnames = list(lab, c(gnames,
if(length(tr)) ''
else NULL)))
if(nw == 1)
cs[(long + 1) : nrow(cs), 1] <- cpct[jstart : nr, ]
else
cs[(long + 1) : nrow(cs), 1 : nw] <- cpct[jstart : nrow(cpct), gnames]
if(lang == 'latex' && dotchart && ncol(pct) <= 3) {
locs <- c(3,-3,5,-5,7,-7,9,-9)
points <- c("\\circle*{4}","\\circle{4}","\\drawline(0,2)(-1.414213562,-1)(1.414213562,-1)(0,2)")
point.loc <-
sapply(jstart:nrow(pct),
function(i) {
paste(ifelse(is.na(pct[i,]), "",
paste0("\\put(", pct[i,], ",0){",
points[1:ncol(pct)],"}")),
collapse='')
})
error.loc <- character(nrow(tab) - exc)
k <- 0
for(i in jstart:ncol(tab)) {
if(i > jstart) {
p1prime <- (tab[,i] + 1)/(denom[i] + 2)
d1 <- p1prime*(1-p1prime)/denom[i]
for(j in jstart:(i-1)) {
k <- k + 1
p2prime <- (tab[,j] + 1)/(denom[j] + 2)
error <- 196 * sqrt(d1 + p2prime * (1 - p2prime)/denom[j])
bar <- ifelse(is.na(error), "",
paste0("\\put(", (pct[,i] + pct[,j])/2 - error, ",",
locs[k],"){\\line(1,0){",error*2,"}}"))
error.loc <- paste0(error.loc, bar)
}
}
}
scale <- character(nrow(tab) - exc)
scale[1] <- "\\multiput(0,2)(25,0){5}{\\color[gray]{0.5}\\line(0,-1){4}}\\put(-5,0){\\makebox(0,0){\\tiny 0}}\\put(108,0){\\makebox(0,0){\\tiny 1}}"
cl <- paste0("\\setlength\\unitlength{1in/100}\\begin{picture}(100,10)(0,-5)",
scale,"\\put(0,0){\\color[gray]{0.5}\\line(1,0){100}}",
point.loc, error.loc,
"\\end{picture}")
cs[(long + 1) : nrow(cs), ncol(cs)] <- cl
}
if(length(tr)) {
ct <- formatTestStats(tr, type == 3,
if(type == 1) 1
else 1 : nr,
prtest, lang=lang, testUsed=testUsed,
pdig=pdig, eps=eps, footnoteTest=footnoteTest,
mspecs=mspecs)
if(length(ct) == 1)
cs[1, ncol(cs)] <- ct
else
cs[(long + 1) : nrow(cs), ncol(cs)] <- ct
}
cs
}
## Function to format subtable for continuous var, for method='reverse'
formatCons <- function(stats, nam, tr, group.freq, prmsd, sep='/',
formatArgs=NULL, round=NULL, prtest,
lang='plain', testUsed=character(0),
middle.bold=FALSE, outer.size=NULL, msdsize=NULL,
brmsd=FALSE, pdig=3, eps=.001, footnoteTest=TRUE,
prob=c(0.25, 0.5, 0.75), prN=FALSE, mspecs=markupSpecs)
{
specs <- mspecs[[lang]]
spc <- specs$space
bold <- if(middle.bold) specs$bold else function(x) x
lspc <- specs$lspace
sup <- specs$sup
br <- specs$br
plminus <- specs$plminus
math <- specs$math
if(lang == 'plain' || ! length(msdsize)) msdsize <- function(x) x
if(! is.function(msdsize)) {
Msdsize <- msdsize
if(lang == 'latex')
msdsize <- function(x) paste0('{\\', Msdsize, ' ', x, '}')
}
if(lang == 'plain') outer.size <- function(x) x
if(! is.function(outer.size)) {
Outer.size <- outer.size
outer.size <- function(x) paste0('{\\', Outer.size, ' ', x, '}')
}
nw <- if(lg <- length(group.freq)) lg else 1
ns <- dimnames(stats)[[2]]
ns <- ifelse(ns %in% c('Mean','SD','N'), '-1', ns)
ns <- as.numeric(ns)
l <- 1:length(ns)
if(length(prob) == 3) {
qs <- numeric(3)
for(i in seq_along(qs)) {
qs[i] <- l[abs(ns - prob[i]) < .001]
}
} else {
q1 <- l[abs(ns - .25) < .001]
med <- l[abs(ns - .5 ) < .001]
q3 <- l[abs(ns - .75) < .001]
qs <- c(q1, med, q3)
}
qu <- stats[,qs,drop=FALSE]
if(prmsd)
qu <- cbind(qu, stats[, c('Mean', 'SD'), drop=FALSE])
if(length(round) && round == 'auto') {
r <- max(abs(stats[, colnames(stats) %nin% c('N', 'SD')]), na.rm=TRUE)
round <- if(r == 0) 2
else max(0, min(5, 3 - round(log10(r))))
}
if(length(round)) qu <- round(qu, round)
ww <- c(list(qu), formatArgs)
cqu <- do.call('format', ww)
if(prN)
cqu <- cbind(cqu,stats[,'N',drop=FALSE])
cqu[is.na(qu)] <- ''
if(lang != 'plain') {
st <- character(nrow(cqu))
names(st) <- dimnames(qu)[[1]]
for(j in 1:nrow(cqu)) {
st[j] <-
paste0(outer.size(cqu[j, 1]), ' ',
bold( cqu[j, 2]), ' ',
outer.size(cqu[j, 3]))
if(prmsd) {
z <- if(brmsd) paste0(br, msdsize(paste0(cqu[j, 4], spc,
plminus, spc, cqu[j, 5])))
else paste0(spc, spc, msdsize(paste0('(', cqu[j, 4], spc,
plminus, cqu[j, 5], ')')))
st[j] <- paste0(st[j], z)
}
if(prN)
st[j] <-
paste0(st[j], outer.size(paste0(spc, math(paste0('N=', cqu[j, ncol(cqu)])))))
}
} else {
if(prmsd) {
st <- apply(cqu, 1,
function(x,sep) paste(x[1], sep, x[2], sep,x[3], ' ',
x[4], '+/-', x[5], sep=''), sep=sep)
} else {
st <- apply(cqu[,seq(3),drop=FALSE], 1, paste, collapse=sep)
}
if(prN) {
st <- setNames(sprintf("%s N=%s", st, cqu[, ncol(cqu), drop=FALSE]),
names(st))
}
}
### if(any(is.na(qu))) st <- "" # Why was this here?
if(nw == 1) yj <- st
else {
yj <- rep('', nw)
names(yj) <- names(group.freq)
yj[names(st)] <- st
}
if(length(tr)) {
ct <- formatTestStats(tr, prtest=prtest, lang=lang,
testUsed=testUsed, pdig=pdig, eps=eps,
footnoteTest=footnoteTest, mspecs=mspecs)
yj <- c(yj, ct)
}
matrix(yj, nrow=1, dimnames=list(nam,names(yj)))
}
formatTestStats <- function(tr, multchoice=FALSE,
i=if(multchoice) NA else 1,
prtest, lang='plain',
testUsed=character(0),
pdig=3, eps=.001,
plotmath=FALSE, footnoteTest=TRUE,
mspecs=markupSpecs)
{
## tr=an element of testresults (created by summary.formula method='reverse')
## or summaryM
if(any(i > 1) && ! multchoice) stop('logic error')
## was i > 1; length mismatch
specs <- mspecs[[lang]]
spc <- specs$space
sup <- specs$sup
math <- specs$math
pval <- tr$P[i]
teststat <- tr$stat[i]
testname <- tr$testname
if(any(is.na(pval)) || any(is.na(teststat))) {
res <- rep('', length(pval))
if(lang == 'latex' && length(testUsed))
res <-
if(footnoteTest)
rep(paste0(sup(match(testname, testUsed))), length(pval))
else rep('', length(pval))
return(res)
}
## Note: multchoice tests always have only one type of d.f.
deg <- if(multchoice) tr$df[i] else tr$df
dof <- if(multchoice) as.character(deg) else paste(deg, collapse=',')
namefun <- specs[[tr$namefun]] ## function for typesetting stat name
statmarkup <-
if(lang == 'latex') tr$latexstat
else if(plotmath) tr$plotmathstat
else tr$statname
if(length(prtest) > 1 && 'stat' %in% prtest &&
(lang != 'plain' || plotmath)) {
if(plotmath) {
## replace "df" inside statmarkup with actual d.f.
if(length(grep('df', statmarkup)))
statmarkup <- sedit(statmarkup, 'df',
if(lang == 'latex' || length(deg) == 1) dof
else paste0('list(', dof, ')'))
} else statmarkup <- namefun(deg)
}
pval <- format.pval(pval, digits=pdig, eps=eps)
plt <- substring(pval,1,1) == '<'
if(any(plt) && lang == 'latex')
pval <- sub('<', '\\\\textless ', pval)
if(lang != 'plain') {
if(length(prtest) == 1)
paste0(
switch(prtest,
P = pval,
stat = format(round(teststat, 2)),
df = dof,
name = statmarkup),
if(footnoteTest && length(testUsed))
paste0(sup(match(testname, testUsed))))
else paste0(
if('stat' %in% prtest)
paste0(statmarkup, '=', format(round(teststat, 2))),
if(all(c('stat', 'P') %in% prtest))
(if(lang == 'html') ', ' else paste0(',', spc)),
if('P' %in% prtest) paste0('P',ifelse(plt,'','='), pval),
if(footnoteTest && length(testUsed))
paste0(sup(match(testname, testUsed))))
} else if(plotmath) {
if(length(prtest) == 1)
parse(text=switch(prtest,
P = ifelse(plt, paste0('~', 'P', pval),
paste0('~', 'P==', pval)),
stat = format(round(teststat, 2)),
dof = format(dof),
name = statmarkup))
else
parse(text=paste(if('stat' %in% prtest)
paste0('~list(',statmarkup,'==',
format(round(teststat,2))),
if(all(c('stat','P') %in% prtest)) ', ',
if('P' %in% prtest)paste0(ifelse(plt,'~P','~P=='),
pval,')')))
} else {
if(length(prtest) == 1)
switch(prtest,
P = pval,
stat = format(round(teststat, 2)),
df = dof,
name = statmarkup)
else
paste(if('stat' %in% prtest)
paste0(statmarkup, '=', format(round(teststat, 2))),
if('df' %in% prtest) paste0('d.f.=', dof),
if('P' %in% prtest) paste0('P', ifelse(plt,'','='), pval))
}
}
latex.summary.formula.reverse <-
function(object, title=first.word(deparse(substitute(object))),
digits, prn = any(n != N), pctdig=0,
what=c('%', 'proportion'),
npct=c('numerator','both','denominator','slash','none'),
npct.size='scriptsize', Nsize='scriptsize',
exclude1=TRUE, vnames=c("labels","names"), prUnits=TRUE,
middle.bold=FALSE, outer.size="scriptsize",
caption, rowlabel="",
insert.bottom=TRUE, dcolumn=FALSE, formatArgs=NULL, round=NULL,
prtest=c('P','stat','df','name'), prmsd=FALSE, msdsize=NULL,
long=dotchart, pdig=3, eps=.001, auxCol=NULL, dotchart=FALSE, ...)
{
x <- object
npct <- match.arg(npct)
vnames <- match.arg(vnames)
what <- match.arg(what)
if(is.logical(prtest) && ! prtest) prtest <- 'none'
stats <- x$stats
nv <- length(stats)
cstats <- lab <- character(0)
nn <- integer(0)
type <- x$type
n <- x$n
N <- x$N
nams <- names(stats)
labels <- x$labels
Units <- x$units
nw <- if(lg <- length(x$group.freq)) lg else 1
gnames <- names(x$group.freq)
test <- x$testresults
if(! length(test)) prtest <- 'none'
mspecs <- markupSpecs
gt1.test <-
if(all(prtest == 'none'))
FALSE
else
length(unique(sapply(test, function(a)a$testname))) > 1
if(!missing(digits)) {
oldopt <- options('digits')
options(digits=digits)
on.exit(options(oldopt))
}
if(missing(caption))
caption <- paste0("Descriptive Statistics",
if(length(x$group.label))
paste(" by",x$group.label)
else
paste0(" $(N=",x$N,")$"))
bld <- if(middle.bold) '\\bf '
else ''
cstats <- NULL
testUsed <- auxc <- character(0)
for(i in 1:nv) {
if(length(auxCol))
auxc <- c(auxc, auxCol[[1]][i])
nn <- c(nn, n[i])
nam <- if(vnames == "names") nams[i]
else labels[i]
if(prUnits && nchar(Units[i]) > 0)
nam <- paste0(nam, '~\\hfill\\tiny{',
gsub('*',' ', Units[i], fixed=TRUE),'}')
tr <- if(length(test) && all(prtest != 'none')) test[[nams[i]]]
else NULL
if(length(test) && all(prtest != 'none'))
testUsed <- unique(c(testUsed, tr$testname))
if(type[i] %in% c(1, 3)) {
cs <- formatCats(stats[[i]], nam, tr, type[i],
if(length(x$group.freq)) x$group.freq else x$n[i],
what, npct, pctdig, exclude1, long, prtest,
lang='latex', testUsed=testUsed,
npct.size=npct.size,
pdig=pdig, eps=eps,
footnoteTest=gt1.test, dotchart=dotchart, mspecs=mspecs)
nn <- c(nn, rep(NA, nrow(cs)-1))
} else cs <- formatCons(stats[[i]], nam, tr, x$group.freq, prmsd,
prtest=prtest, formatArgs=formatArgs, round=round,
lang='latex', testUsed=testUsed,
middle.bold=middle.bold,
outer.size=outer.size, msdsize=msdsize,
pdig=pdig, eps=eps, footnoteTest=gt1.test,
mspecs=mspecs)
cstats <- rbind(cstats, cs)
if(length(auxc) && nrow(cstats) > 1)
auxc <- c(auxc, rep(NA, nrow(cs)-1))
}
lab <- dimnames(cstats)[[1]]
gl <- names(x$group.freq)
if(!length(gl))
gl <- " "
lab <- latexTranslate(lab, c(" "), c("~"), greek=TRUE)
gl <- latexTranslate(gl, greek=TRUE)
extracolheads <-
if(any(gl != " "))
c(if(prn)'', paste0('$N=', x$group.freq, '$'))
else NULL # 21jan03
if(length(test) && !all(prtest == 'none')) {
gl <- c(gl,
if(length(prtest) == 1 && prtest != 'stat')
if(prtest == 'P') 'P-value'
else prtest
else 'Test Statistic')
if(length(extracolheads)) extracolheads <- c(extracolheads,'') # 21jan03
}
dimnames(cstats) <- list(NULL,gl)
cstats <- data.frame(cstats, check.names=FALSE, stringsAsFactors=FALSE)
col.just <- rep("c",length(gl))
if(dcolumn && all(prtest != 'none') &&
gl[length(gl)] %in% c('P-value','Test Statistic'))
col.just[length(col.just)] <- '.'
if(prn) {
cstats <- data.frame(N=nn, cstats, check.names=FALSE,
stringsAsFactors=FALSE)
col.just <- c("r",col.just)
}
if(!insert.bottom)
legend <- NULL
else {
legend <- character()
if(any(type == 2)) {
legend <- paste0("\\noindent {\\", outer.size, " $a$\\ }{", bld,
"$b$\\ }{\\", outer.size,
" $c$\\ } represent the lower quartile $a$, the median $b$, and the upper quartile $c$\\ for continuous variables.",
if(prmsd) '~~$x\\pm s$ represents $\\bar{X}\\pm 1$ SD.'
else '')
}
if(prn) {
legend <- c(legend, '$N$', '~is the number of non--missing values.')
}
if(any(type == 1) && npct == 'numerator') {
legend <- c(legend, 'Numbers after percents are frequencies.')
}
if(length(testUsed))
legend <-c(legend,
if(length(testUsed) == 1)'\\noindent Test used:'
else '\\indent Tests used:',
if(length(testUsed) == 1) paste(testUsed,'test')
else paste(paste0('\\textsuperscript{\\normalfont ',
1:length(testUsed),'}',testUsed,
' test'),collapse='; '))
}
if(length(auxc)) {
if(length(auxc) != nrow(cstats))
stop(paste0('length of auxCol (',length(auxCol[[1]]),
') is not equal to number or variables in table (',
nv,').'))
auxcc <- format(auxc)
auxcc[is.na(auxc)] <- ''
cstats <- cbind(auxcc, cstats)
nax <- names(auxCol)
heads <- get2rowHeads(nax)
names(cstats)[1] <- heads[[1]]
if(length(col.just)) col.just <- c('r', col.just)
if(length(extracolheads)) extracolheads <- c(heads[2], extracolheads)
}
resp <- latex.default(cstats, title=title, caption=caption, rowlabel=rowlabel,
col.just=col.just, numeric.dollar=FALSE,
insert.bottom=legend, rowname=lab, dcolumn=dcolumn,
extracolheads=extracolheads, extracolsize=Nsize,
...)
if(dotchart)
resp$style <- unique(c(resp$style, 'calc', 'epic', 'color'))
resp
}
print.summary.formula.cross <- function(x, twoway=nvar == 2,
prnmiss=any(stats$Missing>0), prn=TRUE,
abbreviate.dimnames=FALSE,
prefix.width=max(nchar(v)),
min.colwidth, formatArgs=NULL,
...)
{
stats <- x
a <- attributes(stats)
cat("\n",a$heading,"\n\n")
attr(stats,'class') <- NULL
ylab <- attr(stats$S,"label")
nvar <- length(a$Levels)
vnames <- names(a$Levels)
nam <- c(vnames, if(prn)"N", if(prnmiss) "Missing", "S")
stats <- stats[nam]
S <- stats$S
ars <- length(dim(S)) # may always be TRUE
attr(stats,"row.names") <- rep("",length(a$row.names))
if(twoway && nvar == 2) {
V <- stats[[vnames[1]]]
H <- stats[[vnames[2]]]
v <- levels(V)
h <- levels(H)
z <- dimnames(stats$S)[[2]]
if(!length(z))
z <- ylab
z <- c(if(prn)"N",
if(prnmiss)"Missing",
z) # 5Oct00
header <- matrix(paste(z,collapse="\n"),1,1)
print.char.matrix(header, col.names=FALSE)
d <- c(length(v),length(h),length(z))
st <- array(NA, dim=d, dimnames=list(v,h,z))
cstats <- array("", dim=d, dimnames=list(v,h,z))
for(i in 1:length(V)) {
j <- V == V[i,drop=FALSE] & H == H[i,drop=FALSE]
st[V[i,drop=FALSE],H[i,drop=FALSE],] <-
c(if(prn)stats$N[j],
if(prnmiss)stats$Missing[j],
if(ars)S[j,]
else S[j])
}
for(k in 1:d[3]) {
ww <- c(list(st[,,k]), formatArgs)
cstats[,,k] <- ifelse(is.na(st[,,k]),"",do.call('format',ww))
}
dimn <- dimnames(cstats)[1:2]
names(dimn) <- vnames
cstats2 <- matrix("", nrow=d[1], ncol=d[2], dimnames=dimn)
for(i in 1:d[1]) {
for(j in 1:d[2]) {
cstats2[i,j] <- paste(cstats[i,j,], collapse="\n")
}
}
if(missing(min.colwidth))
min.colwidth <-
max(min(nchar(dimnames(cstats2)[[2]])),
min(nchar(cstats)[nchar(cstats)>0]))
return(invisible(print.char.matrix(cstats2, col.names=TRUE, ...)))
}
##print.data.frame messes up matrix names (here prefixing by S)
if(ars) {
stats$S <- NULL
snam <- dimnames(S)[[2]]
for(i in 1:ncol(S))
stats[[snam[i]]] <- S[,i]
} else names(stats)[length(stats)] <- ylab
stats <- as.data.frame(stats, stringsAsFactors=FALSE)
invisible(print(stats, ...))
}
latex.summary.formula.cross <-
function(object,
title=first.word(deparse(substitute(object))),
twoway=nvar == 2,
prnmiss=TRUE, prn=TRUE,
caption=attr(object,"heading"), vnames=c('labels','names'),
rowlabel="", ...)
{
stats <- object
vnames <- match.arg(vnames)
ul <- vnames == 'labels'
stats <- unclass(stats)
a <- attributes(stats)
ylab <- attr(stats$S,"label")
nvar <- length(a$Levels)
nam <- c(names(a$Levels),
if(prn)"N",
if(prnmiss)"Missing",
"S")
##Force lazy evaluation since stats about to change
caption <- caption;
title <- title
stats <- stats[nam]
S <- stats$S
ars <- length(dim(S))
inn <- c('cbind','c(','ALL', 'NA')
out <- c('', '(' ,'Total','Missing')
caption <- latexTranslate(caption, inn, out, pb=TRUE, greek=TRUE)
if(twoway)
rowlab <-
if(ul)
latexTranslate(a$labels[1],inn,out,pb=TRUE,greek=TRUE)
else
names(stats)[1]
rvar <- stats[[1]]
cvar <- stats[[2]]
lev1 <- levels(rvar)
lev2 <- levels(cvar)
if(!twoway) {
for(i in 1:nvar)
stats[[i]] <- latexTranslate(as.character(stats[[i]]),inn,
out,pb=TRUE,greek=TRUE)
if(ars) {
stats$S <- NULL
snam <- latexTranslate(dimnames(S)[[2]],inn,out,pb=TRUE,greek=TRUE)
for(i in 1:ncol(S))
stats[[snam[i]]] <- S[,i]
} else names(stats)[length(stats)] <- ylab
stats <- structure(stats, row.names=rep("",length(stats$N)),
class="data.frame")
if(hasArg("col.just")) {
return(latex(stats, title=title, caption=caption, rowlabel=rowlabel, ...))
} else return(latex(stats, title=title, caption=caption, rowlabel=rowlabel,
col.just=c("l","l",rep("r",length(stats)-2)), ...))
}
##Two-way
S <- cbind(N=if(prn)stats$N,
Missing=if(prnmiss && any(stats$Missing)) stats$Missing, #5Oct00
stats$S)
nr <- length(lev1)
nc <- length(lev2)
ns <- ncol(S)
snam <- dimnames(S)[[2]]
snam <- latexTranslate(snam, inn, out, pb=TRUE,greek=TRUE)
dn <-
if(ns > 1)
rep(snam, nc)
else
latexTranslate(lev2,inn,out,pb=TRUE,greek=TRUE) # 5Oct00
st <- matrix(NA, nrow=nr, ncol=nc*ns, dimnames=list(NULL,dn))
for(i in 1:nr) {
l <- 0
for(j in 1:nc) {
w <- rvar == lev1[i] & cvar == lev2[j]
if(any(w))
for(k in 1:ns) {
l <- l+1
st[i,l] <- S[w,k]
}
}
}
latex(st, title=title, caption=caption,
rowlabel=if(rowlabel == '') rowlab else rowlabel,
n.rgroup=c(nrow(st)-1,1),
n.cgroup=if(ns>1) rep(ns,nc), # ns>1 5Oct00
cgroup =if(ns>1) latexTranslate(lev2,inn,out,pb=TRUE,greek=TRUE),
check.names=FALSE,
rowname=latexTranslate(lev1,inn,out,pb=TRUE,greek=TRUE), ...)
}
##stratify is a modification of Therneau's survival4 strata function
##Saves label attributute and defaults shortlabel to T
stratify <- function(..., na.group = FALSE, shortlabel = TRUE)
{
words <- as.list((match.call())[-1])
if(!missing(na.group))
words$na.group <- NULL
if(!missing(shortlabel))
words$shortlabel <- NULL
allf <- list(...)
if(length(allf) == 1 && is.list(ttt <- unclass(allf[[1]]))) {
allf <- ttt
words <- names(ttt)
}
xlab <- sapply(allf, function(x){lab <- valueLabel(x); if(is.null(lab)) NA else lab})
xname <- sapply(allf, function(x){name <- valueName(x); if(is.null(name)) NA else name})
xname <- ifelse(is.na(xname), words, xname)
xlab <- paste(ifelse(is.na(xlab), xname, xlab), collapse=' and ')
xname <- paste(xname, collapse = ' and ')
nterms <- length(allf)
what <- allf[[1]]
if(is.null(levels(what)))
what <- factor(what)
levs <- unclass(what) - 1
wlab <- levels(what)
if(na.group && any(is.na(what))) {
levs[is.na(levs)] <- length(wlab)
wlab <- c(wlab, "NA")
}
if(shortlabel)
labs <- wlab
else labs <- paste(words[1], wlab, sep = "=")
for(i in (1:nterms)[-1]) {
what <- allf[[i]]
if(is.null(levels(what)))
what <- factor(what)
wlab <- levels(what)
wlev <- unclass(what) - 1
if(na.group && any(is.na(wlev))) {
wlev[is.na(wlev)] <- length(wlab)
wlab <- c(wlab, "NA")
}
if(!shortlabel)
wlab <- format(paste(words[i], wlab, sep = "="))
levs <- wlev + levs * (length(wlab))
labs <- paste(rep(labs, rep(length(wlab), length(labs))),
rep(wlab, length(labs)), sep = ", ")
}
levs <- levs + 1
ulevs <- sort(unique(levs[!is.na(levs)]))
levs <- match(levs, ulevs)
labs <- labs[ulevs]
levels(levs) <- labs
class(levs) <- "factor"
if(length(xlab))
valueLabel(levs) <- xlab #FEH 2Jun95
if(length(xname))
valueName(levs) <- xname
levs
}
'[.summary.formula.response' <- function(x,i,j,drop=FALSE)
{
at <- attributes(x)
at$dim <- at$dimnames <- NULL
if(!missing(j)) {
x <- unclass(x)[,j,drop=FALSE]
at$ycolname <- at$ycolname[j]
attributes(x) <- c(attributes(x), at)
}
if(missing(i))
return(x)
if(is.character(i)) {
vn <- at$vname[at$vname != '']
k <- match(i, vn, nomatch=0)
if(any(k == 0))
stop(paste('requested variables not in object:',
paste(i[k == 0],collapse=' ')))
i <- k
}
j <- integer(0)
nl <- at$nlevels
is <- 1
for(m in 1:length(nl)) {
ie <- is+nl[m]-1
if(any(i == m))
j <- c(j,is:ie)
is <- ie+1
}
at$vname <- at$vname[j]
at$vlabel <- at$vlabel[j]
at$nlevels <- at$nlevels[i]
at$labels <- at$labels[i]
x <- unclass(x)[j,,drop=FALSE]
attributes(x) <- c(attributes(x), at)
x
}
cumcategory <- function(y)
{
if(!is.factor(y))
y <- factor(y)
lev <- levels(y)
y <- unclass(y)
Y <- matrix(NA, nrow=length(y), ncol=length(lev)-1,
dimnames=list(NULL, paste0('>=', lev[-1])))
storage.mode(Y) <- 'integer'
for(i in 2:length(lev))
Y[,i-1] <- 1*(y >= i)
Y
}
summarize <- function(X, by, FUN, ...,
stat.name=deparse(substitute(X)),
type=c('variables','matrix'), subset=TRUE,
keepcolnames=FALSE)
{
type <- match.arg(type)
if(missing(stat.name) && length(stat.name) > 1) stat.name <- 'X'
if(!is.list(by)) {
nameby <- deparse(substitute(by))
bylabel <- label(by)
by <- list(by[subset])
names(by) <- if(length(nameby) == 1) nameby
else 'by'
} else {
bylabel <- sapply(by, label)
if(!missing(subset))
by <- lapply(by, function(y, subset) y[subset],
subset=subset)
}
nby <- length(by)
bylabel <- ifelse(bylabel == '', names(by), bylabel)
typical.computation <- FUN(X, ...)
nc <- length(typical.computation)
xlabel <- deparse(substitute(X))
if(length(xlabel) != 1) xlabel <- 'X'
if(length(xlab <- attr(X,'label'))) xlabel <- xlab
if(!missing(subset))
X <- if(is.matrix(X)) X[subset,,drop=FALSE]
else X[subset]
byc <- do.call('paste', c(by, sep='|'))
## split does not handle matrices
## msplit <- function(x, group) {
## if(is.matrix(x)) {
## group <- as.factor(group)
## l <- levels(group)
## res <- vector('list', length(l))
## names(res) <- l
## for(j in l) res[[j]] <- x[group==j,,drop=FALSE]
## res
## } else split(x, group)
## }
## Following was streamlined 10oct02 using the new mApply
## if(nc==1) r <- sapply(msplit(X, byc), FUN, ..., simplify=TRUE) else {
## r <- sapply(msplit(X, byc), FUN, ..., simplify=TRUE)
## r <- matrix(unlist(r), nrow=nc, dimnames=dimnames(r))
## 2Mar00: added unlist because sapply was creating an array of
## lists in S+2000
## }
r <- mApply(X, byc, FUN, ..., keepmatrix=nc > 1)
rdimn <- dimnames(r)[[1]]
## someday can use unpaste defined in Misc.s
ans <- strsplit(if(nc == 1) names(r) else rdimn, '\\|')
ans <- sapply(ans, function(x)if(length(x)) x else '')
## strsplit returns list "transpose" of unpaste
bb <- matrix(unlist(ans), nrow=nby)
ans <- vector('list', nby)
for(jj in 1:nby) ans[[jj]] <- bb[jj,]
names(ans) <- names(by)
if(nc>1 && (nc != ncol(r))) stop('program logic error')
snames <- names(typical.computation)
if(! length(snames)) snames <- paste0(stat.name, 1 : nc)
if(! keepcolnames) {
if(length(stat.name) == 1) snames[1] <- stat.name
else if(length(stat.name)) snames <- stat.name
}
oldopt <- options('warn')
options(warn = -1)
on.exit(options(oldopt))
notna <- rep(TRUE, length(ans[[1]]))
for(i in 1:length(by)) {
byi <- by[[i]]
ansi <- ans[[i]]
if(is.factor(byi)) {
if(!is.character(ansi))
stop('program logic error:ansi not character')
ansi <- factor(ansi, levels(byi))
}
else if(is.numeric(byi))
ansi <- as.numeric(ansi)
names(ansi) <- NULL
label(ansi) <- bylabel[i]
ans[[i]] <- ansi
notna <- notna & !is.na(ansi)
}
if(type == 'matrix' || nc == 1) {
ans[[stat.name]] <-
if(nc == 1)
structure(r, names=NULL)
else
structure(r, dimnames=list(NULL, snames), names=NULL)
label(ans[[stat.name]]) <- xlabel
} else {
snames <- make.names(snames)
for(i in 1:length(snames)) {
ans[[snames[i]]] <- structure(r[, i], names=NULL)
label(ans[[snames[i]]]) <- xlabel
}
}
notna <- notna & !is.na(if(nc == 1) r
else (r %*% rep(1,nc)))
ans <- structure(ans, class='data.frame',
row.names=1 : length(ans[[1]]))
## removed [notna,] from end of above line; not sure why this was needed
iorder <- do.call('order', structure(unclass(ans)[1 : nby], names=NULL))
## order can bomb if data frame given (preserves names)
ans[iorder,]
}
##Following code is based on tapply instead
if(FALSE) {
r <- as.array(tapply(x, by, FUN, ...))
dn <- dimnames(r)
wrn <- .Options$warn
.Options$warn <- -1
for(i in 1:length(by)) {
byi <- by[[i]]
if(is.numeric(byi) && !is.factor(byi)) dn[[i]] <- as.numeric(dn[[i]])
}
.Options$warn <- wrn
names(dn) <- names(by)
ans <- expand.grid(dn)
typical.computation <- FUN(x, ...)
nc <- length(typical.computation)
snames <- names(typical.computation)
if(length(snames)) snames <- paste(stat.name, snames) else
snames <- if(nc == 1) stat.name else paste(stat.name, 1 : nc)
for(i in 1 : length(r)) if(!length(r[[i]])) r[[i]] <- rep(NA, nc)
## unlist will skip positions where calculations not done (NULLs)
S <- matrix(unlist(r), ncol=length(snames),
dimnames=list(NULL, snames), byrow=TRUE)
if(type == 'matrix') {
ans$S <- S
if(stat.name != 'S') names(ans)[length(ans)] <- stat.name
} else ans <- cbind(ans, S)
ans
}
smean.cl.normal <- function(x, mult=qt((1+conf.int)/2,n-1),
conf.int=.95, na.rm=TRUE)
{
if(na.rm) x <- x[!is.na(x)]
n <- length(x)
if(n < 2)
return(c(Mean=mean(x),Lower=NA,Upper=NA))
xbar <- sum(x)/n
se <- sqrt(sum((x - xbar)^2) / n / (n-1))
c(Mean=xbar, Lower=xbar - mult*se, Upper=xbar + mult*se)
}
smean.sd <- function(x, na.rm=TRUE)
{
if(na.rm)
x <- x[!is.na(x)]
n <- length(x)
if(n == 0)
return(c(Mean=NA, SD=NA))
xbar <- sum(x)/n
sd <- sqrt(sum((x - xbar)^2)/(n-1))
c(Mean=xbar, SD=sd)
}
smean.sdl <- function(x, mult=2, na.rm=TRUE)
{
if(na.rm)
x <- x[!is.na(x)]
n <- length(x)
if(n == 0)
return(c(Mean=NA, Lower=NA, Upper=NA))
xbar <- sum(x)/n
sd <- sqrt(sum((x - xbar)^2)/(n-1))
c(Mean=xbar, Lower=xbar - mult * sd, Upper=xbar + mult * sd)
}
#S-Plus gives a parse error for R's .Internal()
#Might try not using an else to see if S still parses
smean.cl.boot <- function(x, conf.int=0.95, B=1000, na.rm=TRUE, reps=FALSE) {
if(na.rm)
x <- x[!is.na(x)]
n <- length(x)
xbar <- mean(x)
if(n < 2L)
return(c(Mean=xbar, Lower=NA, Upper=NA))
z <- unlist(lapply(seq_len(B), function(i, x, N) sum(x[sample.int(N, N, TRUE, NULL)]),
x=x, N=n)) / n
quant <- quantile(z, c((1 - conf.int)/2, (1 + conf.int)/2))
names(quant) <- NULL
res <- c(Mean=xbar, Lower=quant[1L], Upper=quant[2L])
if(reps)
attr(res, "reps") <- z
res
}
smedian.hilow <- function(x, conf.int=.95, na.rm=TRUE)
{
quant <- quantile(x, probs=c(.5,(1-conf.int)/2,(1+conf.int)/2), na.rm=na.rm)
names(quant) <- c('Median','Lower','Upper')
quant
}
asNumericMatrix <- function(x)
{
a <- attributes(x)
k <- length(a$names)
at <- vector('list', k); names(at) <- a$names
for(i in 1:k) {
xi <- x[[i]]
type <- storage.mode(xi)
A <- attributes(xi)
if(type == 'character') {
xi <- factor(xi)
A <- c(A, attributes(xi))
x[[i]] <- xi
}
A$dim <- A$names <- A$dimnames <- NULL
A$.type. <- type
at[[i]] <- A
}
resp <- matrix(unlist(x), ncol=k,
dimnames=list(a$row.names, a$names))
attr(resp, 'origAttributes') <- at
resp
}
matrix2dataFrame <- function(x, at=attr(x, 'origAttributes'), restoreAll=TRUE)
{
d <- dimnames(x)
k <- length(d[[2]])
w <- vector('list',k)
nam <- names(w) <- d[[2]]
for(i in 1 : k) {
a <- at[[nam[i]]]
type <- a$.type.
a$.type. <- NULL
xi <- x[, i]
names(xi) <- NULL
lev <- a$levels
if(restoreAll) {
if(type == 'character') {
xi <- as.character(factor(xi, 1 : length(lev), lev))
a$levels <- NULL
if(length(a$class)) a$class <- setdiff(a$class, 'factor')
}
storage.mode(xi) <- type
## R won't let something be assigned class factor by brute
## force unless it's an integer object
attributes(xi) <- a
} else {
if(length(l <- a$label)) label(xi) <- l
if(length(u <- a$units)) units(xi) <- u
if(length(lev)) {
xi <- factor(xi, 1 : length(lev), lev)
if(type == 'character') xi <- as.character(xi)
}
}
w[[i]] <- xi
}
rn <- d[[1]]
if(! length(rn)) rn <- as.character(seq(along=xi))
structure(w, class='data.frame', row.names=rn)
}
stripChart <- function(x, xlim, xlab='', pch=1,
cex.labels=par('cex'), cex.points=.5,
lcolor='gray',
grid=FALSE)
{
if(grid) sRequire('lattice')
groups <- names(x)
if(missing(xlim))
xlim <- range(unlist(x),na.rm=TRUE)
i <- integer(0)
if(grid) {
lines <- lattice::llines
points <- lattice::lpoints
segments <- lattice::lsegments
}
plot.new()
mai <- omai <- par('mai')
on.exit(par(mai=omai))
mxlab <- .3+max(strwidth(groups, units='inches', cex=cex.labels))
mai[2] <- mxlab
par(mai=mai, new=TRUE)
plot(xlim, c(.5,length(groups)+.5), xlim=xlim, xlab='', ylab='',
axes=FALSE, type='n')
box()
mgp.axis(1, axistitle=xlab)
mtext(paste(groups,''), 2, 0, at=length(groups):1,
adj=1, las=1, cex=cex.labels)
y <- 0
abline(h = 1:length(groups), lty = 1, lwd=1, col=lcolor)
for(Y in length(groups):1) {
y <- y + 1
X <- x[[y]]
if(length(X))
points(X, rep(Y, length(X)), pch=pch)
}
}
conTestkw <- function(group,x) {
st <- spearman2(group,x)
list(P = st['P'],
stat = st['F'],
df = st[c('df1','df2')],
testname = if(st['df1'] == 1) 'Wilcoxon' else 'Kruskal-Wallis',
statname = 'F',
namefun = 'fstat',
latexstat = 'F_{df}',
plotmathstat = 'F[df]')
}
catTestchisq=function(tab) {
st <-
if(!is.matrix(tab) || nrow(tab) < 2 || ncol(tab) < 2)
list(p.value=NA, statistic=NA, parameter=NA)
else {
rowcounts <- tab %*% rep(1, ncol(tab))
tab <- tab[rowcounts > 0,]
if(!is.matrix(tab))
list(p.value=NA, statistic=NA, parameter=NA)
else chisq.test(tab, correct=FALSE)
}
list(P = st$p.value,
stat = st$statistic,
df = st$parameter,
testname = 'Pearson',
statname = 'Chi-square',
namefun = 'chisq',
latexstat = '\\chi^{2}_{df}',
plotmathstat = 'chi[df]^2')
}
ordTestpo=function(group, x) {
if (!requireNamespace("rms", quietly = TRUE))
stop("This function requires the 'rms' package.")
f <- rms::lrm(x ~ group)$stats
list(P = f['P'],
stat = f['Model L.R.'],
df = f['d.f.'],
testname = 'Proportional odds likelihood ratio',
statname = 'Chi-square',
namefun = 'chisq',
latexstat = '\\chi^{2}_{df}',
plotmathstat = 'chi[df]^2')
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.