From 93031d294c79feea69fcdda891c3955327fc8f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20H=C3=B8jsgaard?= Date: Thu, 31 Oct 2024 23:31:55 +0100 Subject: [PATCH] SH: --- R/api_array_parray.R | 242 -------------- R/api_array_pct.R | 85 ----- R/api_array_properties.R | 25 +- R/api_array_simulate.R | 6 +- R/api_array_tabX.R | 627 +++++++++++++++++++++++------------ R/api_array_tab_create.R | 154 --------- R/api_array_tableX_bristol.R | 88 ++--- R/graph_coerce_list.R | 6 +- R/graph_coerce_xxx2yyy.R | 6 +- R/graph_is.R | 10 +- R/graph_properties.R | 4 +- R/grbase_utilities.R | 25 +- R/yyOLD_grbase.R | 4 - 13 files changed, 504 insertions(+), 778 deletions(-) delete mode 100755 R/api_array_parray.R delete mode 100644 R/api_array_pct.R delete mode 100755 R/api_array_tab_create.R diff --git a/R/api_array_parray.R b/R/api_array_parray.R deleted file mode 100755 index 87c73df..0000000 --- a/R/api_array_parray.R +++ /dev/null @@ -1,242 +0,0 @@ -######################################################################### -#' -#' @title Representation of and operations on multidimensional arrays -#' @description General representation of multidimensional arrays -#' (with named dimnames, also called named arrays.) -#' @name api-parray -#' -######################################################################### -#' -#' @details -#' -#' A named array object represents a table defined by a set of -#' variables and their levels, together with the values of the -#' table. E.g. f(a,b,c) can be a table with a,b,c representing levels -#' of binary variable -#' -#' If \code{normalize="first"} then for each configuration of all -#' other variables than the first, the probabilities are normalized to -#' sum to one. Thus f(a,b,c) becomes a conditional probability table -#' of the form p(a|b,c). -#' -#' If \code{normalize="all"} then the sum over all entries of f(a,b,c) -#' is one. -#' -#' If \code{smooth} is positive then \code{smooth} is added to -#' \code{values} before normalization takes place. -#' -#' @param varNames Names of variables defining table; can be a right hand sided -#' formula. -#' @param levels Either 1) a vector with number of levels of the factors in -#' varNames or 2) a list with specification of the levels of the factors in -#' varNames. See 'examples' below. -#' @param values Values to go into the array -#' @param normalize Either "none", "first" or "all". Should result be -#' normalized, see 'Details' below. -#' @param smooth Should values be smoothed, see 'Details' below. -#' @return A a named array. -#' @author Søren Højsgaard, \email{sorenh@@math.aau.dk} -#' @seealso \code{\link{is.named.array}} -#' @keywords utilities -#' @examples -#' -#' t1 <- parray(c("gender","answer"), list(c('male','female'),c('yes','no')), values=1:4) -#' t1 <- parray(~gender:answer, list(c('male','female'),c('yes','no')), values=1:4) -#' t1 <- parray(~gender:answer, c(2,2), values=1:4) -#' -#' t2 <- parray(c("answer","category"), list(c('yes','no'),c(1,2)), values=1:4+10) -#' t3 <- parray(c("category","foo"), c(2,2), values=1:4+100) -#' -#' varNames(t1) -#' nLevels(t1) -#' valueLabels(t1) -#' -#' ## Create 1-dimensional vector with dim and dimnames -#' x1 <- 1:5 -#' as.parray(x1) -#' x2 <- parray("x", levels=length(x1), values=x1) -#' dim(x2) -#' dimnames(x2) -#' -#' ## Matrix -#' x1 <- matrix(1:6, nrow=2) -#' as.parray(x1) -#' parray(~a:b, levels=dim(x1), values=x1) -#' -#' ## Extract parrays from data -#' ## 1) a dataframe -#' data(cad1) -#' data2parray(cad1, ~Sex:AngPec:AMI) -#' data2parray(cad1, c("Sex","AngPec","AMI")) -#' data2parray(cad1, c(1,2,3)) -#' ## 2) a table -#' data2parray(UCBAdmissions,c(1,2), normalize="first") - - -#' @export parray -parray <- function(varNames, levels, values=1, normalize="none", smooth=0){ - - normalize <- match.arg(normalize, choices=c("none", "first", "all")) - varNames <- rhsFormula2list(varNames)[[1]] - if (smooth>0){ - values <- values + smooth - } - - dn <- makeDimNames(varNames, levels) - nlev <- unlist(lapply(dn, length)) - ans <- array(values, dim=nlev, dimnames=dn) - - ## Normalize if requested - switch(normalize, - "first" = { - ##cat("first\n") - if (length(nlev)>1){ - tmp <- matrix(ans, ncol=dim(ans)[1], byrow=TRUE) - ans[] <- t.default(tmp/rowSums(tmp)) - } else { - ans <- ans / sum(ans) - }}, - "all" = { - ans <- ans / sum(ans) - }, - "none" = { } ) - class(ans) <- c("parray","array") - return(ans) -} - - -#' @export -#' @rdname api-parray -as.parray <- function(values, normalize="none", smooth=0){ - - normalize <- match.arg(normalize, choices=c("none", "first", "all")) - - if (!inherits(values, c("array","matrix","integer","double","table"))){ - stop("arg must be array, matrix, table, integer or double\n") - } - - if (smooth>0){ - values <- values + smooth - } - - if (is.null(dimnames(values))){ - if (!is.null(dim(values))) - nLevels <- dim(values) - else - nLevels <- length(values) - - varNames <- paste("V", 1:length(nLevels),sep='') - dimnames <- makeDimNames(varNames, nLevels) - ans <- array(values, dim = nLevels, dimnames = dimnames) - } else { - ans <- values - } - ##class(ans) <- c("parray","array") - - switch(normalize, - "first"={ - if (length(dim(ans))>1){ - marg <- 2:length(dim(ans)) - ma <- apply(ans, marg, sum) - ans <- sweep(ans, marg, ma, "/") - } else { - ans <- ans / sum(ans) - } - }, - "all"={ans <- ans / sum(ans) - }, - "none"={} - ) - attr(ans, "call") <- NULL - return(ans) -} - -#' @param data Data to be coerced to a `parray`; can be `data.frame`, -#' `table`, `xtabs`, `matrix`. -#' @export -#' @rdname api-parray -data2parray <- function(data, varNames=NULL, normalize="none", smooth=0){ - ## FIXME: should be inherits - cls <- match(class(data), c("data.frame","table", "xtabs", "matrix"))[1] - if (is.na(cls)){ - stop("'data' must be one of dataframe, table, xtabs, matrix") - } - - .set.varNames <- function(varNames, dataNames){ - if (is.null(varNames)){ - if (is.null(dataNames)) - stop("'data' has no variable names") - varNames <- dataNames - } else { - if (class(varNames) %in% c("formula", "character")){ - varNames <- rhsf2list(varNames)[[1]] - } - } - varNames - } - - switch(as.character(cls), - "1"={ - dataNames <- names(data) - varNames <- .set.varNames(varNames, dataNames) - val <- xtabs(~., data = data[, varNames, drop = FALSE]) - }, - "2"=, "3"=, "4"={ - dataNames <- names(dimnames(data)) - varNames <- .set.varNames(varNames, dataNames) - val <- tableMargin(data, varNames) - }) - attr(val, "call") <- NULL - res <- as.parray(val, normalize = normalize, smooth = smooth) - res -} - -#' @param sep Desired separator in dim names; defaults to "". -#' @export -#' @rdname api-parray -makeDimNames <- function(varNames, levels, sep=''){ - if (!is.character(varNames)) - stop("'varNames' is not character vector") - if (missing(levels)) - stop("'levels' is missing") - if (! (is.list(levels) || is.numeric(levels)) ) - stop("'levels' must be a list or a numeric vector") - - if ( is.list(levels) ) { - if ( is.null(names(levels)) ){ - if (length(varNames) != length(levels)) - stop("kkk") - names(levels) <- varNames - } else { - n <- match(varNames, names(levels)) - if (any(is.na(n))) - stop("ppp") - levels <- levels[n] - } - } else { - levels <- .make_vn( varNames, levels ) # Levels is numeric vector - } - levels -} - - -.make_vn <- function(varNames, levels){ - if (!is.character(varNames)) - stop("'varNames' must be character") - if (!is.numeric(levels)) - stop("'levels' must be numeric") - if (length(varNames) != length(levels)) - stop("'varNames' and 'levels' does not have the same length") - out <- lapply(seq_along(varNames), function(i) - { - ll <- levels[[ i ]] - vv <- varNames[ i ] - lev <- paste(vv, 1:ll, sep="") - lev - }) - names(out) <- varNames - out -} - - - diff --git a/R/api_array_pct.R b/R/api_array_pct.R deleted file mode 100644 index b269ce8..0000000 --- a/R/api_array_pct.R +++ /dev/null @@ -1,85 +0,0 @@ -######################################################## -#' @title Array algebra -#' @description Addition, subtraction etc. of arrays -#' @name api-pct-operations -#' @author Søren Højsgaard, \email{sorenh@@math.aau.dk} -######################################################## -#' -#' @param a,a1,a2 Arrays (with named dimnames) -## #' @param lst List of arrays. -#' @param tab1,tab2 Multidimensional arrays with named dimnames -#' (we call them 'named arrays'). -#' @param perm A vector of indices or dimnames or a right hand sided -#' formula giving the desired permutiation. -#' @param marg A vector of indices or dimnames or a right hand sided -#' formula giving the desired marginal. -#' @param slice A list of the form name=value. -## #' @param eps Criterion for checking equality of two arrays. -#' @param extra List defining the extra dimensions. -## #' @param aux Either a list with names and dimnames or a named array -## #' from which such a list can be extracted. -#' @aliases %a+% %a-% %a*% %a/% %a/0% -#' -#' @examples -#' hec <- HairEyeColor -#' a1 <- tabMarg(hec, c("Hair", "Eye")) -#' a2 <- tabMarg(hec, c("Hair", "Sex")) -#' a3 <- tabMarg(hec, c("Eye", "Sex")) -#' -#' ## Binary operations -#' a1 %a+% a2 -#' a1 %a-% a2 -#' a1 %a*% a2 -#' a1 %a/% a2 - -#' @export -#' @rdname api-pct-operations -"%a+%" <- function(a1, a2){tabAdd(a1,a2)} - -#' @export -#' @rdname api-pct-operations -"%a-%" <- function(a1, a2){tabSubt(a1,a2)} - -#' @export -#' @rdname api-pct-operations -"%a*%" <- function(a1, a2){tabMult(a1,a2)} - -#' @export -#' @rdname api-pct-operations -"%a/%" <- function(a1, a2){tabDiv(a1,a2)} - -#' @export -#' @rdname api-pct-operations -"%a/0%" <- function(a1, a2){tabDiv0(a1,a2)} - -#' @export -#' @rdname api-pct-operations -"%a_%" <- function(tab1, marg){tabMarg(tab1, marg)} - -#' @export -#' @rdname api-pct-operations -"%a==%" <- function(tab1, tab2){tabEqual(tab1, tab2)} - -#' @export -#' @rdname api-pct-operations -"%a^%" <- function(tab1, extra){tabExpand(tab1, extra)} - -#' @export -#' @rdname api-pct-operations -"%aperm%" <- function(tab1, perm){tabPerm(tab1, perm)} - -#' @export -#' @rdname api-pct-operations -"%aalign%" <- function(tab1, tab2){tabAlign(tab1, tab2)} - -#' @export -#' @rdname api-pct-operations -"%aslice%" <- function(tab1, slice){tabSlice(tab1, slice)} - -#' @export -#' @rdname api-pct-operations -"%aslice*%" <- function(tab1, slice){tabSliceMult(tab1, slice)} - -#' @export -#' @rdname api-pct-operations -"%amarg%" <- function(tab1, marg){tabMarg(tab1, marg)} diff --git a/R/api_array_properties.R b/R/api_array_properties.R index b3feb5c..eb8cda0 100755 --- a/R/api_array_properties.R +++ b/R/api_array_properties.R @@ -12,32 +12,32 @@ #' @param obj Some R object. #' @param a1,a2 Arrays with named dimnames. #' -## #' @seealso \code{\link{is.named.array}} +## #' @seealso \code{\link{is_named_array}} #' @examples -#' is.named.array( HairEyeColor ) -#' is.named.array( matrix(1:4, nrow=2) ) +#' is_named_array( HairEyeColor ) +#' is_named_array( matrix(1:4, nrow=2) ) #' is_named_array_( HairEyeColor ) #' is_named_array_( matrix(1:4, nrow=2) ) #' is_number_vector_(1:4) #' is_number_vector_(list(1:4)) #' -#' ar1 = tabNew(c("a", "b"), levels=c(2, 3)) -#' ar2 = tabNew(c("c", "a"), levels=c(2, 2)) +#' ar1 = tab_new(c("a", "b"), levels=c(2, 3)) +#' ar2 = tab_new(c("c", "a"), levels=c(2, 2)) #' ar1 #' ar2 #' ## dimension a has levels a1,a2 in both ar1 and ar2. #' # Hence we have a match. #' dimnames_match(ar1, ar2) #' -#' ar1 = tabNew(c("a", "b"), levels=c(2, 3)) -#' ar2 = tabNew(c("c", "a"), levels=c(2, 3)) +#' ar1 = tab_new(c("a", "b"), levels=c(2, 3)) +#' ar2 = tab_new(c("c", "a"), levels=c(2, 3)) #' ar1 #' ar2 #' ## dimension a has levels a1,a2 in ar1 and levels a1,a2,a3 in ar2. #' # Hence we do not have a match. #' dimnames_match(ar1, ar2) #' -#' ar2 = tabNew(c("c", "a"), levels=list(c=c("c1", "c2"), a=c("a2", "a1"))) +#' ar2 = tab_new(c("c", "a"), levels=list(c=c("c1", "c2"), a=c("a2", "a1"))) #' ar2 #' ## dimension a has levels a1,a2 in ar1 and levels a2,a1 in ar2. #' # Hence we do not have a match. @@ -45,6 +45,11 @@ #' @export #' @rdname api-array-properties +is_named_array <- is_named_array_ + +## FIXME: Needed for gRain +#' @export +#' @rdname api-array-properties is.named.array <- is_named_array_ #' @export @@ -62,9 +67,9 @@ is_dimnames_ <- is_dimnames_ #' @export #' @rdname api-array-properties dimnames_match <- function( a1, a2 ){ - if ( !is.named.array( a1 ) ) + if ( !is_named_array( a1 ) ) stop("'a1' is not a named array \n") - if ( !is.named.array( a2 ) ) + if ( !is_named_array( a2 ) ) stop("'a2' is not a named array \n") dn1 <- dimnames( a1 ) diff --git a/R/api_array_simulate.R b/R/api_array_simulate.R index 1ac3ec8..f18962d 100755 --- a/R/api_array_simulate.R +++ b/R/api_array_simulate.R @@ -24,9 +24,7 @@ #' @keywords utilities #' @examples #' ## 2x2 array -#' x <- parray(c("a", "b"), levels=c(2, 2), values=1:4) -#' -#' x <- tabNew(c("a", "b"), levels=c(2, 2), values=1:4) +#' x <- tab_new(c("a", "b"), levels=c(2, 2), values=1:4) #' #' ## Simulate from entire array #' s <- simulateArray(x, 1000) @@ -37,7 +35,7 @@ #' xtabs(~., as.data.frame(s)) #' #' ## 2 x 2 x 2 array -#' x <- parray(c("a", "b", "c"), levels=c(2, 2, 2), values=1:8) +#' x <- tab_new(c("a", "b", "c"), levels=c(2, 2, 2), values=1:8) #' ## Simulate from entire array #' s <-simulateArray(x, 36000) #' xtabs(~., as.data.frame(s)) diff --git a/R/api_array_tabX.R b/R/api_array_tabX.R index 15ba5b9..678f152 100755 --- a/R/api_array_tabX.R +++ b/R/api_array_tabX.R @@ -1,3 +1,128 @@ + + +################################################################## +#' @title Create multidimensional arrays +#' @description Alternative ways of creating arrays +#' @name api_tab_new +#' @author Søren Højsgaard, \email{sorenh@@math.aau.dk} +################################################################## +#' +#' @details +#' +#' 1. If \code{normalize="first"} then for each configuration of all +#' other variables than the first, the probabilities are +#' normalized to sum to one. Thus f(a, b, c) becomes a +#' conditional probability table of the form p(a | b, c). +#' +#' 1. If \code{normalize="all"} then the sum over all entries of +#' f(a,b,c) is one. +#' +#' 1. If \code{smooth} is positive then \code{smooth} is added to +#' \code{values} BEFORE normalization takes place. +#' +#' @param names Names of variables defining table; either a character +#' vector or a right hand sided formula. +#' @param levels 1) a list with specification of the levels of the +#' factors in \code{names} or 2) a vector with number of levels of +#' the factors in \code{names}. See 'examples' below. +#' @param values values to go into the array. +#' @param normalize Either "none", "first" or "all". Should result be +#' normalized, see 'Details' below. +#' @param smooth Should values be smoothed, see 'Details' below. +#' @return An array. +#' @keywords utilities +#' @examples +#' +#' universe <- list(gender=c('male', 'female'), +#' answer=c('yes', 'no'), +#' rain=c('yes', 'no')) +#' t1 <- tab_new(c("gender", "answer"), levels=universe, values=1:4) +#' t1 +#' t2 <- tab_new(~gender:answer, levels=universe, values=1:4) +#' t2 +#' t3 <- tab_new(~gender:answer, c(2, 2), values=1:4) +#' t3 +NULL + +#' @export +#' @rdname api_tab_new +tab_new <- function(names, levels, values, normalize="none", smooth=0) { + + make_dimnames <- function(names, levels){ + if ( !(is.atomic(names) && is.numeric(levels)) ) + stop("Can not create dimnames") + + if (length(names) != length(levels)) + stop("'names' and 'levels' must have the same length") + + dn <- lapply(seq_along(levels), + function(i){ 1:levels[i] }) + + names(dn) <- names + return(dn) + } + + if (missing(values)) + values <- 1 + if (smooth > 0) + values <- values + smooth + + normalize <- match.arg(normalize, choices=c("none", "first", "all")) + nms <- rhsFormula2list(names)[[1]] + + if (is.list(levels)) + { + if (length(levels) == 0) { + stop("Can not create table\n") + } + if (length(levels) == 1) { + vn <- names(levels) + levels <- rep(levels, length(nms)) + names(levels) <- nms + dn <- lapply(levels, function(d) rhsf2list(d)[[1]]) + di <- unlist(lapply(dn, length), use.names=FALSE) + } + else if (length(levels) > 0) { + if (!is_named_list(levels)) { + stop("not all elements in 'levels' are named\n") + } + vn <- names(levels) + idx <- match(nms, vn) + if (any((b <- is.na(idx)))) { + stop(sprintf("Levels for variable(s): %s not found\n", + toString(nms[b]))) + } + levels <- levels[idx] ## those used + dn <- lapply(levels, function(d) rhsf2list(d)[[1]]) + di <- unlist(lapply(dn, length), use.names=FALSE) + } + + } + else if (is.numeric(levels)) + { + di <- levels + dn <- make_dimnames(nms, levels) + } + else if (is.character(levels)) + { + dn <- rep(list(levels), length(nms)) + names(dn) <- nms + di <- unlist(lapply(dn, length), use.names=FALSE) + } else { + stop("Can not create 'tab' object") + } + + + if (is.atomic(values) && !is.object(values)) { + out <- array(values, dim=di, dimnames=dn) + } + tab_normalize(out, normalize) +} + + + + + ## #################################################################### #' #' @title Interface - operations on multidimensional arrays. @@ -19,10 +144,7 @@ #' are computed. If 2 then 0 slices are inserted. #' @param op The algebraic operation to be carried out. #' -## #' @aliases -## #' tab_align_ -## #' tab_expand_ tab_marg_ tab_perm_ -#' +NULL ## ------------------------ ## Aliases for cpp functions @@ -30,38 +152,32 @@ #' @export #' @rdname api-tabX -tabAdd <- tab_add_ +tab_add <- tab_add_ -#' @export -#' @rdname api-tabX -tabAlign <- tab_align_ #' @export #' @rdname api-tabX -tabDiv <- tab_div_ +tab_align <- tab_align_ #' @export #' @rdname api-tabX -tabDiv0 <- tab_div0_ +tab_div <- tab_div_ + + #' @export #' @rdname api-tabX -tabOp <- tab_op_ +tab_div0 <- tab_div0_ + + #' @export #' @rdname api-tabX -tabEqual <- tab_equal_ +tab_op <- tab_op_ #' @export #' @rdname api-tabX -tabExpand <- function(tab, aux, type=0L) { ## FIXME Rethink this - - if (is.list(aux)) - aux <- lapply(aux, rhsf2vec) - - tab_expand_(tab, aux, type) -} - +tab_equal <- tab_equal_ ## tabMult used by grain; #' @export @@ -70,15 +186,20 @@ tabMult <- tab_mult_ #' @export #' @rdname api-tabX -tabSubt <- tab_subt_ +tab_mult <- tab_mult_ #' @export #' @rdname api-tabX -tabListMult <- tab_list_mult_ +tab_subt <- tab_subt_ #' @export #' @rdname api-tabX -tabListAdd <- tab_list_add_ +tab_list_mult <- tab_list_mult_ + +#' @export +#' @rdname api-tabX +tab_list_add <- tab_list_add_ + ## ------------------------- @@ -87,58 +208,64 @@ tabListAdd <- tab_list_add_ #' @export #' @rdname api-tabX -tabPerm <- function(tab, perm) { - if (!is.named.array(tab)) stop("'tab' not a named array") - if (!(is.numeric(perm) || is.character(perm) || inherits(perm, "formula"))) - stop("'perm' must be character/numeric vector or right hand sided formula") +tab_expand <- function(tab, aux, type=0L) { ## FIXME Rethink this + + if (is.list(aux)) + aux <- lapply(aux, rhsf2vec) + + tab_expand_(tab, aux, type) +} + +#' @export +#' @rdname api-tabX +tab_perm <- function(tab, perm) { + stopifnot_named_array(tab) - perm <- .get_perm_or_marg(tab, perm) - ##cat("perm : ", toString(perm), "\n") + perm <- set_spec_to_char(tab, perm) tab_perm_(tab, perm) } + #' @export #' @rdname api-tabX -tabMarg <- function(tab, marg=NULL) { - if (!is.named.array(tab)) stop("'tab' not a named array") - if (!is.null(marg)) - if (!(is.numeric(marg) || is.character(marg) || inherits(marg, "formula"))) - stop("'marg' must be character/numeric vector or right hand sided formula") - - marg <- .get_perm_or_marg(tab, marg) - ##cat("perm : ", toString(perm), "\n") +tab_marg <- function(tab, marg=NULL) { + stopifnot_named_array(tab) + + marg <- set_spec_to_char(tab, marg) tab_marg_(tab, marg) } +#' @export +#' @rdname api-tabX +tabMarg <- tab_marg #' @export #' @rdname api-tabX -tabSum <- function(tab, ...) { +tab_sum <- function(tab, ...) { if (missing(tab)) return(0) args <- c(list(tab), list(...)) - tabListAdd(listify_dots(args)) + tab_list_add(listify_dots(args)) } #' @export #' @rdname api-tabX -tabProd <- function(tab, ...) { +tab_prod <- function(tab, ...) { if (missing(tab)) return(0) args <- c(list(tab), list(...)) - tabListMult(listify_dots(args)) + tab_list_mult(listify_dots(args)) } + + #' @export #' @rdname api-tabX -tabNormalize <- function(tab, type="none") { - ## cat("tabNormalize\n"); print(tab) +tab_normalize <- function(tab, type="none") { + ## cat("tab_normalize\n"); print(tab) switch(type, "first"={ if (length(dim(tab)) > 1){ - ## tab <- tabPerm(tabDiv(tab, tabMarg(tab, 2:length(dim(tab)))), - ## names(dimnames(tab))) - ## Perhaps faster than above? - tab <- tab / rep(tabMarg(tab, 2:length(dim(tab))), each=dim(tab)[1]) - + denom <- rep(tab_marg(tab, 2:length(dim(tab))), each=dim(tab)[1]) + tab <- tab / denom } else { tab <- tab / sum(tab) } @@ -150,12 +277,7 @@ tabNormalize <- function(tab, type="none") { } -## FIXME: Document tabDist -## marg and cond: Disjoint sets, possibly NULL. Given either as -## character vectors or integer vectors or rhs-formulae. -## Returns p( marg | cond ). -## There is one other option for cond: A named list with a simple conditioning set. -## In this case, the array is sent to a arSlice. + ## #################################################################### ## @@ -163,11 +285,11 @@ tabNormalize <- function(tab, type="none") { #' @description Marginalize and condition in a multidimensional array #' which is assumed to represent a discrete multivariate #' distribution. -#' @name api-tabDist +#' @name api_tab_dist ## ######################################################################## #' -#' @aliases tabDist +#' @aliases tab_dist_worker #' #' @param tab Multidimensional array with dimnames. #' @param marg A specification of the desired margin; a character vector, a @@ -184,54 +306,54 @@ tabNormalize <- function(tab, type="none") { #' #' hec <- HairEyeColor #' -#' is.named.array( hec ) +#' is_named_array( hec ) #' ## We need dimnames, and names on the dimnames #' #' ## Marginalize: -#' tabDist(hec, marg= ~Hair + Eye) -#' tabDist(hec, marg= ~Hair:Eye) -#' tabDist(hec, marg= c("Hair", "Eye")) -#' tabDist(hec, marg= 1:2) +#'tabDist(hec, marg= ~Hair + Eye) +#'tabDist(hec, marg= ~Hair:Eye) +#'tabDist(hec, marg= c("Hair", "Eye")) +#'tabDist(hec, marg= 1:2) #' -#' tabDist(hec, marg= ~Hair + Eye, normalize=FALSE) +#'tabDist(hec, marg= ~Hair + Eye, normalize=FALSE) #' #' ## Condition -#' tabDist(hec, cond= ~Sex + Hair) -#' tabDist(hec, cond= ~Sex:Hair) -#' tabDist(hec, cond= c("Sex", "Hair")) -#' tabDist(hec, cond= c(3,1)) +#'tabDist(hec, cond= ~Sex + Hair) +#'tabDist(hec, cond= ~Sex:Hair) +#'tabDist(hec, cond= c("Sex", "Hair")) +#'tabDist(hec, cond= c(3,1)) #' -#' tabDist(hec, cond= list(Hair="Black")) -#' tabDist(hec, cond= list(Hair=1)) +#'tabDist(hec, cond= list(Hair="Black")) +#'tabDist(hec, cond= list(Hair=1)) #' #' \dontrun{ #' ## This will fail -#' tabDist(hec, cond= list(Hair=c("Black", "Brown"))) -#' tabDist(hec, cond= list(Hair=1:2)) +#'tabDist(hec, cond= list(Hair=c("Black", "Brown"))) +#'tabDist(hec, cond= list(Hair=1:2)) #' } #' ## But this will do the trick -#' a <- tabSlice(hec, slice=list(Hair=c("Black", "Brown"))) -#' tabDist(a, cond=~Hair) +#' a <- tab_slice(hec, slice=list(Hair=c("Black", "Brown"))) +#'tabDist(a, cond=~Hair) #' #' ## Combined -#' tabDist(hec, marg=~Hair+Eye, cond=~Sex) -#' tabDist(hec, marg=~Hair+Eye, cond="Sex") +#'tabDist(hec, marg=~Hair+Eye, cond=~Sex) +#'tabDist(hec, marg=~Hair+Eye, cond="Sex") #' -#' tabDist(hec, marg=~Hair+Eye, cond=list(Sex="Male")) -#' tabDist(hec, marg=~Hair+Eye, cond=list(Sex="Male"), normalize=FALSE) +#'tabDist(hec, marg=~Hair+Eye, cond=list(Sex="Male")) +#'tabDist(hec, marg=~Hair+Eye, cond=list(Sex="Male"), normalize=FALSE) #' -#' tabDist(hec, cond=list(Sex="Male")) -#' tabDist(hec, cond=list(Sex="Male"), normalize=FALSE) +#'tabDist(hec, cond=list(Sex="Male")) +#'tabDist(hec, cond=list(Sex="Male"), normalize=FALSE) #' NULL #' @export -#' @rdname api-tabDist +#' @rdname api_tab_dist tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { if (!is.list(cond)) - .tabDist(tab, marg=marg, cond=cond, normalize=normalize) - else{ + tab_dist_worker(tab, marg=marg, cond=cond, normalize=normalize) + else { ## Are there formulae in cond? ## print(cond) idx <- sapply(cond, function(x) inherits(x, "formula")) @@ -260,25 +382,31 @@ tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { condset <- c(cond1, cond3) ##str(list(marg=marg, condset=condset, condnv=condnv)) - - ## ALternative : use tabSlice if (!is.null(condnv)) - tab <- .tabDist(tab, cond=condnv, normalize=normalize) + tab <- tab_dist_worker(tab, cond=condnv, normalize=normalize) - ## if (!is.null(condset)) - tab <- .tabDist(tab, marg=marg, cond=condset, normalize=normalize) + tab <- tab_dist_worker(tab, marg=marg, cond=condset, normalize=normalize) return(tab) } } ## ' @export -## ' @rdname api-tabDist -.tabDist <- function(tab, marg=NULL, cond=NULL, normalize=TRUE){ +## ' @rdname api_tab_dist +tab_dist_worker <- function(tab, marg=NULL, cond=NULL, normalize=TRUE) { + + .is.simple.cond <- function( cond ) { ## What is this + z <- unlist(lapply(cond, is.logical), use.names=FALSE) + has.logical <- any( z ) + u <- unlist(lapply(cond, length), use.names=FALSE) + is.short <- all( u == 1 ) + if ( !has.logical && is.short ) TRUE + else if (!all( unlist( cond[ z ] ) ) ) + stop("'cond' is not simple but contains FALSE values; not allowed") + else FALSE + } ## str(list(marg=marg, cond=cond)) - - if (!is.named.array(tab)) - stop("'tab' must be a named array") + stopifnot_named_array(tab) if (any(tab < 0)) stop("'tab' must be non-negative") @@ -290,9 +418,8 @@ tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { if (!.is.simple.cond( cond )) stop("'cond' is not 'simple'; can not proceed\n") else { - ##message("calling tabDist again") - tab <- tabSlice(tab, slice = cond, as.array = TRUE) - tabDist(tab, marg=marg, normalize=normalize) + tab <- tab_slice(tab, slice = cond, as.array = TRUE) + tab_dist_worker(tab, marg=marg, normalize=normalize) } } else { vset <- names(dimnames( tab )) @@ -314,18 +441,18 @@ tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { ##str(list(marg=marg, cond=cond, mset=mset, cset=cset, mcset=mcset)) if (!is.null(mcset)){ - tab <- tabMarg(tab, marg = mcset) + tab <- tab_marg(tab, marg = mcset) } if (length(cset) == 0){ if (normalize) tab <- tab / sum(tab) } else { - mtab <- tabMarg(tab, marg=cset) - tab <- tabDiv(tab, mtab) + mtab <- tab_marg(tab, marg=cset) + tab <- tab_div(tab, mtab) } if (length(mcset) > 0) - if (!is.null(mcset)) tabPerm(tab, mcset) else tab + if (!is.null(mcset)) tab_perm(tab, mcset) else tab } } @@ -337,7 +464,7 @@ tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { #' #' @title Array slices #' @description Functions for extracting slices of arrays -#' @name api_tabSlice +#' @name api_tab_slice #' @author Søren Højsgaard, \email{sorenh@@math.aau.dk} #' ## ######################################################################## @@ -345,7 +472,7 @@ tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { #' @param tab An array with named dimnames. #' @param slice A list defining the slice. #' @param margin Names of variables in slice. -#' @param margin.idx Indec of variables in slice. +## #' @param margin.idx Indec of variables in slice. #' @param drop If TRUE then dimensions with only one level will be #' dropped from the output. #' @param as.array If the resulting array is one-dimensional the @@ -363,54 +490,52 @@ tabDist <- function (tab, marg = NULL, cond = NULL, normalize = TRUE) { #' x = HairEyeColor #' s = list(Hair=c("Black", "Brown"), Eye=c("Brown", "Blue")) #' -#' s1 = tabSlice(x, slice=s); s1 +#' s1 = tab_slice(x, slice=s); s1 #' -#' tabSlice2Entries(x, slice=s) -#' tabSlice2Entries(x, slice=s, complement=TRUE) +#' tab_slice_to_entries(x, slice=s) +#' tab_slice_to_entries(x, slice=s, complement=TRUE) #' -#' ## tabSliceMult -#' s2 = tabSliceMult(x, slice=s); s2 +#' ## tab_slice_mult +#' s2 = tab_slice_mult(x, slice=s); s2 #' #' sp = list(c(1,2), c(1,2), TRUE) -#' tabSlicePrim(x, slice=sp) -#' tabSlice(x, slice=s) +#' tab_slice_prim(x, slice=sp) +#' tab_slice(x, slice=s) NULL #' @export -#' @rdname api_tabSlice -tabSlice<- function(tab, slice=NULL, margin=names(slice), drop=TRUE, as.array=FALSE) { - - if (!is.named.array(tab)) - stop("'tab' is not a named array") - else if ( is.null( slice ) ) - tab - else if (!( is.character( slice ) || is.numeric( slice ) || is.list( slice ))) - stop("'slice' is not valid \n") - else if (is.null( margin ) || !( is.character( margin ) || is.numeric( margin ))) - stop("'margin' is not valid \n") - else { - dn <- names(dimnames(tab)) - margin.idx <- if (is.character(margin)){ - match(margin, dn) - } else margin - - if (any(idx <- is.na(margin.idx))){ - cat("Error: Names not in domain : ", toString(margin[idx]), "\n") - stop("Invalid 'margin'") +#' @rdname api_tab_slice +tab_slice <- function(tab, slice=NULL, margin=names(slice), drop=TRUE, as.array=FALSE) { + + stopifnot_named_array(tab) + + if ( is.null( slice ) ) + return(tab) + else if (!( is.character( slice ) || is.numeric( slice ) || is.list( slice ))) + stop("'slice' is not valid \n") + else if (is.null( margin ) || !( is.character( margin ) || is.numeric( margin ))) + stop("'margin' is not valid \n") + else { + dn <- names(dimnames(tab)) + margin.idx <- if (is.character(margin)){ + match(margin, dn) + } else margin + + if (any(idx <- is.na(margin.idx))){ + cat("Error: Names not in domain : ", toString(margin[idx]), "\n") + stop("Invalid 'margin'") + } + tab_slice_worker(tab, slice, margin.idx, drop=drop, as.array=as.array) } - tabSlice2(tab, slice, margin.idx, drop=drop, as.array=as.array) - } } -#' @export -#' @rdname api_tabSlice -tabSlice2 <- function(tab, slice, margin.idx, drop=TRUE, as.array=FALSE) { +tab_slice_worker <- function(tab, slice, margin.idx, drop=TRUE, as.array=FALSE) { z <- as.list(rep(TRUE, length(dim(tab)))) z[ margin.idx ] <- slice out <- do.call("[", c(list(tab), z, drop=drop)) - if (as.array && is.null( dim( out ) ) ){ + if (as.array && is.null(dim( out ))) { dn <- list(names(out)) k <- which(unlist(lapply(z, is.logical))) # idx of variables still in array names(dn) <- names( dimnames( tab ) )[ k ] @@ -420,31 +545,33 @@ tabSlice2 <- function(tab, slice, margin.idx, drop=TRUE, as.array=FALSE) { } } + #' @export -#' @rdname api_tabSlice -tabSlicePrim <- function(tab, slice, drop=TRUE) { +#' @rdname api_tab_slice +tab_slice_prim <- function(tab, slice, drop=TRUE) { do.call("[", c(list(tab), slice, drop=drop)) } #' @export -#' @rdname api_tabSlice -tabSliceMult <- function(tab, slice, val=1, comp=0) { +#' @rdname api_tab_slice +tab_slice_mult <- function(tab, slice, val=1, comp=0) { if ( !is.null(val) ){ - idx <- tabSlice2Entries(tab, slice) + idx <- tab_slice_to_entries(tab, slice) tab[idx] <- tab[idx] * val } if ( !is.null(comp) ){ - idx <- tabSlice2Entries(tab, slice, complement=TRUE) + idx <- tab_slice_to_entries(tab, slice, complement=TRUE) tab[idx] <- tab[idx] * comp } tab } + #' @export -#' @rdname api_tabSlice -tabSlice2Entries <- function(tab, slice, complement=FALSE) { +#' @rdname api_tab_slice +tab_slice_to_entries <- function(tab, slice, complement=FALSE) { tab[] <- 1:length(tab) - out <- tabSlice(tab, slice, margin=names(slice)) + out <- tab_slice(tab, slice, margin=names(slice)) if (complement) c(tab)[-c(out)] else @@ -453,6 +580,57 @@ tabSlice2Entries <- function(tab, slice, complement=FALSE) { +### COMPATIBILITY with gRain and gRim + + +## FIXME used in gRain +#' @export +#' @rdname api_tab_new +tabNew <- tab_new + +## FIXME grain +#' @export +#' @rdname api_tab_slice +tabSliceMult <- tab_slice_mult + + +## FIXME gRain +#' @export +#' @rdname api-tabX +tabDiv <- tab_div_ + +## FIXME gRain +#' @export +#' @rdname api-tabX +tabDiv0 <- tab_div0_ + +## FIXME gRain +#' @export +#' @rdname api_tab_slice +tabSlice <- tab_slice + +## FIXME gRain +#' @export +#' @rdname api-tabX +tabPerm <- tab_perm + + +## FIXME gRain +#' @export +#' @rdname api-tabX +tabProd <- tab_prod + +## FIXME gRain +#' @export +#' @rdname api-tabX +tabNormalize <- tab_normalize + + +#' @export +#' @rdname api-tabX +tabListMult <- tab_list_mult_ + + ## ######################################################## @@ -461,20 +639,8 @@ tabSlice2Entries <- function(tab, slice, complement=FALSE) { ## ## ######################################################## -.is.simple.cond <- function( cond ) { - z <- unlist(lapply(cond, is.logical), use.names=FALSE) - has.logical <- any( z ) - u <- unlist(lapply(cond, length), use.names=FALSE) - is.short <- all( u == 1 ) - if ( !has.logical && is.short ) TRUE - else if (!all( unlist( cond[ z ] ) ) ) - stop("'cond' is not simple but contains FALSE values; not allowed") - else FALSE -} -.is.named.list <- function(x) { - is.list( x ) && !is.null( names( x ) ) -} +## FIXME: gør disse to funktioner mon ikke næsten det samme? .spec2char <- function(x) { if (is.null( x )) x @@ -489,83 +655,106 @@ tabSlice2Entries <- function(tab, slice, complement=FALSE) { x } -.get_perm_or_marg <- function(tab, perm) { - if (inherits(perm, "formula")){ ## A right hand sided formula - perm <- all.vars(perm[[2]]) +set_spec_to_char <- function(tab, set_spec) { + + if (!(is.numeric(set_spec) || is.character(set_spec) || inherits(set_spec, "formula"))) + stop("'set_spec' must be character/numeric vector or right hand sided formula") + + if (inherits(set_spec, "formula")){ ## A right hand sided formula + set_spec <- all.vars(set_spec[[2]]) } - if (is.character(perm)){ ## Allow for name abbreviation + if (is.character(set_spec)){ ## Allow for name abbreviation vn <- names(dimnames( tab )) - p <- pmatch(perm, vn) - perm <- vn[p] + p <- pmatch(set_spec, vn) + set_spec <- vn[p] } - perm + set_spec } -## #' ################################################################### -## #' -## #' @title Convert dataframe to contingency table -## #' @description: Much like xtabs but with more flexibility -## #' @name df2xtabs -## #' -## ## ################################################################### -## #' -## #' @param indata A dataframe. -## #' @param names Names of variables defining table; a character vector -## #' or a right hand sided formula. -## #' @param normalize Either "none", "first" or "all". Should result be -## #' normalized, see 'Details' below. -## #' @param smooth Should values be smoothed, see 'Details' below. -## #' -## #' @examples -## #' ## Extract arrays from dataframe (much like xtabs() but with more flexibility) -## #' data(cad1) -## #' df2xtabs(cad1, ~Sex:AngPec:AMI) -## #' df2xtabs(cad1, c("Sex", "AngPec", "AMI")) -## #' df2xtabs(cad1, c(1, 2, 3)) - -## df2xtabs <- function(indata, names=NULL, normalize="none", smooth=0){ - -## if ( !( is.data.frame(indata) ) ) -## stop("'indata' must a dataframe\n") - -## if (!is.null( names )) { -## if (is.numeric( names )){ -## if (min(names) < 1 || max(names) > ncol(indata)){ -## stop("columns out of range \n") -## } -## } else { -## if (class(names) %in% c("formula", "character")){ -## names <- rhsf2list(names)[[1]] -## } else { -## stop("don't know what to do\n") -## } -## } -## } - -## out <- if (is.null(names)) xtabs(~., data=indata) -## else xtabs(~., data=indata[, names, drop=FALSE]) - -## ## FIXME : There is no check on what smooth is -## if (smooth > 0) -## out <- out + smooth - -## if (normalize != "none") -## tabNormalize( out, normalize ) -## else out -## } +######################################################## +#' @title Array algebra +#' @description Addition, subtraction etc. of arrays +#' @name api_ops_pct +#' @author Søren Højsgaard, \email{sorenh@@math.aau.dk} +######################################################## +#' +#' @param a,a1,a2 Arrays (with named dimnames) +## #' @param lst List of arrays. +#' @param tab1,tab2 Multidimensional arrays with named dimnames +#' (we call them 'named arrays'). +#' @param perm A vector of indices or dimnames or a right hand sided +#' formula giving the desired permutiation. +#' @param marg A vector of indices or dimnames or a right hand sided +#' formula giving the desired marginal. +#' @param slice A list of the form name=value. +## #' @param eps Criterion for checking equality of two arrays. +#' @param extra List defining the extra dimensions. +## #' @param aux Either a list with names and dimnames or a named array +## #' from which such a list can be extracted. +#' @aliases %a+% %a-% %a*% %a/% %a/0% +#' +#' @examples +#' hec <- HairEyeColor +#' a1 <- tab_marg(hec, c("Hair", "Eye")) +#' a2 <- tab_marg(hec, c("Hair", "Sex")) +#' a3 <- tab_marg(hec, c("Eye", "Sex")) +#' +#' ## Binary operations +#' a1 %a+% a2 +#' a1 %a-% a2 +#' a1 %a*% a2 +#' a1 %a/% a2 + +#' @export +#' @rdname api_ops_pct +"%a+%" <- function(a1, a2){tab_add(a1,a2)} +#' @export +#' @rdname api_ops_pct +"%a-%" <- function(a1, a2){tab_subt(a1,a2)} +#' @export +#' @rdname api_ops_pct +"%a*%" <- function(a1, a2){tab_mult(a1,a2)} +#' @export +#' @rdname api_ops_pct +"%a/%" <- function(a1, a2){tab_div(a1,a2)} +#' @export +#' @rdname api_ops_pct +"%a/0%" <- function(a1, a2){tab_div0(a1,a2)} +#' @export +#' @rdname api_ops_pct +"%a_%" <- function(tab1, marg){tab_marg(tab1, marg)} +#' @export +#' @rdname api_ops_pct +"%a==%" <- function(tab1, tab2){tab_equal(tab1, tab2)} -## if (!is.named.array(tab)) stop("'tab' not a named array") -## if (!is.null(aux)) -## if (!(is.numeric(aux) || is.character(aux) || inherits(aux, "formula"))) -## stop("'aux' must be character/numeric vector or right hand sided formula") +#' @export +#' @rdname api_ops_pct +"%a^%" <- function(tab1, extra){tab_expand(tab1, extra)} -## aux <- .get_perm_or_marg(tab, aux) +#' @export +#' @rdname api_ops_pct +"%aperm%" <- function(tab1, perm){tab_perm(tab1, perm)} +#' @export +#' @rdname api_ops_pct +"%aalign%" <- function(tab1, tab2){tab_align(tab1, tab2)} + +#' @export +#' @rdname api_ops_pct +"%aslice%" <- function(tab1, slice){tab_slice(tab1, slice)} + +#' @export +#' @rdname api_ops_pct +"%aslice*%" <- function(tab1, slice){tab_slice_mult(tab1, slice)} + +#' @export +#' @rdname api_ops_pct +"%amarg%" <- function(tab1, marg){tab_marg(tab1, marg)} diff --git a/R/api_array_tab_create.R b/R/api_array_tab_create.R deleted file mode 100755 index 1c87ddf..0000000 --- a/R/api_array_tab_create.R +++ /dev/null @@ -1,154 +0,0 @@ - -################################################################## -#' @title Create multidimensional arrays -#' @description Alternative ways of creating arrays -#' @name api-tabNew -#' @author Søren Højsgaard, \email{sorenh@@math.aau.dk} -################################################################## -#' -#' @details -#' -#' 1. If \code{normalize="first"} then for each configuration of all -#' other variables than the first, the probabilities are -#' normalized to sum to one. Thus f(a, b, c) becomes a -#' conditional probability table of the form p(a | b, c). -#' -#' 1. If \code{normalize="all"} then the sum over all entries of -#' f(a,b,c) is one. -#' -#' 1. If \code{smooth} is positive then \code{smooth} is added to -#' \code{values} BEFORE normalization takes place. -#' -#' @param names Names of variables defining table; either a character -#' vector or a right hand sided formula. -#' @param levels 1) a list with specification of the levels of the -#' factors in \code{names} or 2) a vector with number of levels of -#' the factors in \code{names}. See 'examples' below. -#' @param values values to go into the array. -#' @param normalize Either "none", "first" or "all". Should result be -#' normalized, see 'Details' below. -#' @param smooth Should values be smoothed, see 'Details' below. -#' @return An array. -#' @keywords utilities -#' @examples -#' -#' universe <- list(gender=c('male', 'female'), -#' answer=c('yes', 'no'), -#' rain=c('yes', 'no')) -#' t1 <- tabNew(c("gender", "answer"), levels=universe, values=1:4) -#' t1 -#' t2 <- tabNew(~gender:answer, levels=universe, values=1:4) -#' t2 -#' t3 <- tabNew(~gender:answer, c(2, 2), values=1:4) -#' t3 -NULL - -#' @export -#' @rdname api-tabNew -tabNew <- function(names, levels, values, normalize="none", smooth=0) { - - ## print("tabNew") - - normalize <- match.arg(normalize, choices=c("none", "first", "all")) - names <- rhsFormula2list(names)[[1]] - - if (is.list(levels)) - { - if (length(levels) == 0){ - stop("Can not create table\n") - } - if (length(levels) == 1){ - vn <- names(levels) - levels <- rep(levels, length(names)) - names(levels) <- names - dn <- lapply(levels, function(d) rhsf2list(d)[[1]]) - di <- unlist(lapply(dn, length), use.names=FALSE) - - } else if (length(levels) > 0){ - if (!is_named_list(levels)){ - stop("not all elements in 'levels' are named\n") - } - vn <- names(levels) - idx <- match(names, vn) - if (any((b <- is.na(idx)))){ - stop(sprintf("Levels for variable(s): %s not found\n", - toString(names[b]))) - } - levels <- levels[idx] ## those used - dn <- lapply(levels, function(d) rhsf2list(d)[[1]]) - di <- unlist(lapply(dn, length), use.names=FALSE) - } - - } - else if (is.numeric(levels)) - { - di <- levels - dn <- make_dimnames(names, levels) - } - else if (is.character(levels)) - { - dn <- rep(list(levels), length(names)) - names(dn) <- names - di <- unlist(lapply(dn, length), use.names=FALSE) - } else { - stop("Can not create 'tab' object") - } - - if (missing(values)) - values <- 1 - if (smooth > 0) - values <- values + smooth - - if (is.atomic(values) && !is.object(values)){ - out <- array(values, dim=di, dimnames=dn) - } - tabNormalize(out, normalize) -} - - -is_named_list <- function(x) { - if (!inherits(x, "list")) - return(FALSE) - vn <- names(x) - if (is.null(vn)) - return(FALSE) - all(nchar(vn) > 0) -} - - -## FIXME make_dimnames findes også (cirka) i parray. Redundans -make_dimnames <- function(names, levels){ - if ( !(is.atomic(names) && is.numeric(levels)) ) - stop("Can not create dimnames") - - if (length(names) != length(levels)) - stop("'names' and 'levels' must have the same length") - - dn <- lapply(seq_along(levels), - function(i){ - 1:levels[i] - }) - - names(dn) <- names - dn -} - - - - - - - ## print(vn) - ## if (!all(sapply(vn, nchar) > 0)){ - ## print(vn) - ## stop("not all elements in 'levels' are named\n") - ## } - ## idx <- match(names, vn) - ## if (any((b <- is.na(idx)))) - ## stop(sprintf("Levels for variable(s): %s not found\n", - ## toString(names[b]))) - ## else { - ## levels <- levels[idx] ## those used - ## dn <- lapply(levels, function(d) rhsf2list(d)[[1]]) - ## di <- unlist(lapply(dn, length), use.names=FALSE) - ## } diff --git a/R/api_array_tableX_bristol.R b/R/api_array_tableX_bristol.R index 1abd463..f84baee 100755 --- a/R/api_array_tableX_bristol.R +++ b/R/api_array_tableX_bristol.R @@ -20,7 +20,7 @@ #' @export #' @rdname api-array-07 -tablePerm <- function(tab, perm, resize=TRUE, keep.class=FALSE){ +tablePerm <- function(tab, perm, resize=TRUE, keep.class=FALSE) { # Like aperm() but perm can be dimnames if (missing( perm )){ perm <- integer(0) @@ -41,13 +41,13 @@ tablePerm <- function(tab, perm, resize=TRUE, keep.class=FALSE){ #' @export #' @rdname api-array-07 -tableMult <- function(tab1, tab2){ +tableMult <- function(tab1, tab2) { tableOp(tab1, tab2, op="*") } #' @export #' @rdname api-array-07 -tableDiv <- function(tab1, tab2){ +tableDiv <- function(tab1, tab2) { tableOp(tab1, tab2, op="/") } @@ -55,7 +55,7 @@ tableDiv <- function(tab1, tab2){ #' @export #' @rdname api-array-07 #' @param op The operation; choices are \code{"*"}, \code{"/"}, \code{"+"}, \code{"-"}. -tableOp <- function(tab1, tab2, op="*"){ +tableOp <- function(tab1, tab2, op="*") { if (!is.array(tab1)) {stop("'tab1' is not an array")} if (!is.array(tab2)) {stop("'tab2' is not an array")} @@ -119,7 +119,7 @@ tableOp <- function(tab1, tab2, op="*"){ #' @export #' @rdname api-array-07 #' @param restore Not so clear anymore. -tableOp2 <- function (tab1, tab2, op = `*`, restore = FALSE){ +tableOp2 <- function (tab1, tab2, op = `*`, restore = FALSE) { if (!is.array(tab1)) {stop("'tab1' is not an array")} if (!is.array(tab2)) {stop("'tab2' is not an array")} @@ -156,8 +156,8 @@ tableOp2 <- function (tab1, tab2, op = `*`, restore = FALSE){ #' @rdname api-array-07 tableOp0 <- function(tab1, tab2, op=`*`){ - if (!is.named.array(tab1)) {stop("'tab1' is not an array")} - if (!is.named.array(tab2)) {stop("'tab2' is not an array")} + if (!is_named_array(tab1)) {stop("'tab1' is not an array")} + if (!is_named_array(tab2)) {stop("'tab2' is not an array")} vn1 <- names(dimnames(tab1)) vn2 <- names(dimnames(tab2)) @@ -181,43 +181,6 @@ tableOp0 <- function(tab1, tab2, op=`*`){ -## #' @export -## #' @rdname api-array-07 -## #' @param restore Not so clear anymore. -## tableOp2 <- function (tab1, tab2, op = `*`, restore = FALSE){ - -## if (!is.array(tab1)) {stop("'tab1' is not an array")} -## if (!is.array(tab2)) {stop("'tab2' is not an array")} - -## vn1 <- names(dimnames(tab1)) -## vn2 <- names(dimnames(tab2)) - -## ## indices of vn2 in vn1: -## vn2.idx <- match(vn2, vn1) -## ## Create perumation indices; first variables in vn2; then vn1\vn2 -## perm <- c(vn2.idx, (1:length(vn1))[-vn2.idx]) - -## pot1 <- -## if (restore) { -## zz <- op(aperm.default(tab1, perm, TRUE), as.numeric(tab2)) -## newvn <- c(vn2, vn1[-vn2.idx]) -## perm2 <- match(vn1, newvn) -## aperm.default(zz, perm2, TRUE) -## } else { -## op(aperm.default(tab1, perm, TRUE), as.numeric(tab2)) -## } -## if (identical(op, `/`)) -## pot1[!is.finite(pot1)] <- 0 -## pot1 -## } - - - - - - - - @@ -444,6 +407,43 @@ tableSetSliceValue <- function(tab, margin, level, complement=FALSE, value=0){ +## #' @export +## #' @rdname api-array-07 +## #' @param restore Not so clear anymore. +## tableOp2 <- function (tab1, tab2, op = `*`, restore = FALSE){ + +## if (!is.array(tab1)) {stop("'tab1' is not an array")} +## if (!is.array(tab2)) {stop("'tab2' is not an array")} + +## vn1 <- names(dimnames(tab1)) +## vn2 <- names(dimnames(tab2)) + +## ## indices of vn2 in vn1: +## vn2.idx <- match(vn2, vn1) +## ## Create perumation indices; first variables in vn2; then vn1\vn2 +## perm <- c(vn2.idx, (1:length(vn1))[-vn2.idx]) + +## pot1 <- +## if (restore) { +## zz <- op(aperm.default(tab1, perm, TRUE), as.numeric(tab2)) +## newvn <- c(vn2, vn1[-vn2.idx]) +## perm2 <- match(vn1, newvn) +## aperm.default(zz, perm2, TRUE) +## } else { +## op(aperm.default(tab1, perm, TRUE), as.numeric(tab2)) +## } +## if (identical(op, `/`)) +## pot1[!is.finite(pot1)] <- 0 +## pot1 +## } + + + + + + + + ## #' @export ## #' @rdname api-array-07 diff --git a/R/graph_coerce_list.R b/R/graph_coerce_list.R index 6b8a672..b054424 100755 --- a/R/graph_coerce_list.R +++ b/R/graph_coerce_list.R @@ -156,7 +156,7 @@ g_adl2XX_ <- function(zz, outtype) { #' @export #' @rdname graph_coerce_list g_M2adl_ <- function( amat ){ - .check.is.matrix( amat ) + check_is_matrix( amat ) if (!isadjMAT_( amat )) stop("' amat ' not an adjacency matrix\n") vn <- colnames( amat ) r <- rowmat2list__( amat ) @@ -170,14 +170,14 @@ g_M2adl_ <- function( amat ){ #' @rdname graph_coerce_list g_M2ugl_ <- function( amat ){ ## FIXME: M2ugList: Need a check for undirectedness - .check.is.matrix( amat ) + check_is_matrix( amat ) max_cliqueMAT( amat )[[1]] } #' @export #' @rdname graph_coerce_list g_M2dagl_ <- function( amat ){ - .check.is.matrix( amat ) + check_is_matrix( amat ) vn <- colnames( amat ) c <- colmat2list( amat ) i <- lapply(c, function(z) which(z != 0)) diff --git a/R/graph_coerce_xxx2yyy.R b/R/graph_coerce_xxx2yyy.R index 4b1e4aa..09db163 100755 --- a/R/graph_coerce_xxx2yyy.R +++ b/R/graph_coerce_xxx2yyy.R @@ -83,21 +83,21 @@ g_ig2sm_ <- function(object) { #' @export #' @rdname graph-coerce-api g_xm2ig_ <- function( object ){ ## M | igraph - .check.is.matrix( object ) + check_is_matrix( object ) as(object , "igraph") } #' @export #' @rdname graph-coerce-api g_xm2dm_ <- function( object ){ ## M - .check.is.matrix( object ) + check_is_matrix( object ) M2matrix__(object) } #' @export #' @rdname graph-coerce-api g_xm2sm_ <- function( object ){ ## M - .check.is.matrix( object ) + check_is_matrix( object ) M2dgCMatrix__(object) } diff --git a/R/graph_is.R b/R/graph_is.R index f264cdc..e6588a2 100644 --- a/R/graph_is.R +++ b/R/graph_is.R @@ -87,7 +87,7 @@ is_dag.igraph <- function(object){ #' @export is_dag.default <- function( object ){ - .check.is.matrix(object) + check_is_matrix(object) isdagMAT_(object) } @@ -114,7 +114,7 @@ is_ug.igraph <- function(object){ #' @export is_ug.default <- function(object){ - .check.is.matrix(object) + check_is_matrix(object) isugMAT_(object) } #' @export @@ -140,7 +140,7 @@ is_tug.igraph <- function(object){ #' @export is_tug.default <- function(object){ - .check.is.matrix(object) + check_is_matrix(object) if (isugMAT_(object)) length(mcsMAT(object)) > 0 else FALSE } @@ -168,7 +168,7 @@ is_dg.igraph <- function(object){ #' @export is_dg.default <- function(object){ - .check.is.matrix(object) + check_is_matrix(object) eps <- 1e-4 if (isadjMAT_(object)) max(abs(sum(object * t(object)))) <= eps @@ -187,7 +187,7 @@ is_dgMAT <- function(object){ #' @export #' @rdname graph_is is_adjMAT <- function(object){ - .check.is.matrix(object) + check_is_matrix(object) isadjMAT_(object) } diff --git a/R/graph_properties.R b/R/graph_properties.R index 6cf9e09..d9e8a49 100755 --- a/R/graph_properties.R +++ b/R/graph_properties.R @@ -84,7 +84,7 @@ isGraphical.default <- function( x ){ x <- formula(delete.response(terms(x))) x <- rhsf2list(x) } else { - if (!.is_list_of_atomic(x)) + if (!is_list_of_atomic(x)) stop("'x' must be a list of atomic vectors") if (length(x) == 0) stop("'x' must have positive length") @@ -122,7 +122,7 @@ isDecomposable.default <- function( x ){ x <- formula(delete.response(terms(x))) x <- rhsf2list(x) } else { - if (!.is_list_of_atomic(x)) + if (!is_list_of_atomic(x)) stop("'x' must be a list of atomic vectors") if (length(x) == 0) stop("'x' must have positive length") diff --git a/R/grbase_utilities.R b/R/grbase_utilities.R index 2dd366d..19b0127 100755 --- a/R/grbase_utilities.R +++ b/R/grbase_utilities.R @@ -1,20 +1,39 @@ -.check.is.matrix <- function(x){ +check_is_matrix <- function(x){ if (!inherits(x, c("matrix", "dgCMatrix"))) stop("Input must be a matrix or a dgCMatrix\n") } -.check.is.igraph <- function(x){ +check_is_igraph <- function(x){ if (!inherits(x, "igraph")) stop("'x' not an igraph object...") } -.is_list_of_atomic <- function(z){ +is_list_of_atomic <- function(z){ is.list(z) && all(sapply(z, is.atomic)) } +is_named_list <- function(x) { + if (!inherits(x, "list")) + return(FALSE) + vn <- names(x) + if (is.null(vn)) + return(FALSE) + all(nchar(vn) > 0) +} + +.is.named.list <- function(x) { + is.list( x ) && !is.null( names( x ) ) +} + + +stopifnot_named_array <- function(tab){ + if (!is_named_array(tab)) stop("'tab' not a named array") +} + + ## ################################################################### ## #' @title gRbase utilities diff --git a/R/yyOLD_grbase.R b/R/yyOLD_grbase.R index a4b0e52..5879fcf 100755 --- a/R/yyOLD_grbase.R +++ b/R/yyOLD_grbase.R @@ -202,14 +202,10 @@ nLevels.default <- function(x) dim(x) ## nLevels.array <- function(x) dim(x) -## nLevels.parray <- function(x) dim(x) ##varNames.array <- function(x) names(attr(x,"dimnames")) ##valueLabels.array <- function(x) attr(x,"dimnames") -##varNames.parray <- function(x) names(attr(x,"dimnames")) -##valueLabels.parray <- function(x) attr(x,"dimnames") - ## ## END of French update ##