diff --git a/.gitignore b/.gitignore index cbdc1146..1a5d4154 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,6 @@ Rplots.pdf revdep/ /doc/ /Meta/ - # Claude Code local settings .claude/ +.DS_Store diff --git a/DESCRIPTION b/DESCRIPTION index f23cec91..82fafac4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -74,7 +74,8 @@ Imports: rgl, colorspace, gt, - scales + scales, + methods Description: Provides additional data sets, methods and documentation to complement the 'vcd' package for Visualizing Categorical Data and the 'gnm' package for Generalized Nonlinear Models. In particular, 'vcdExtra' extends mosaic, assoc and sieve plots from 'vcd' to handle 'glm()' and 'gnm()' models and diff --git a/NAMESPACE b/NAMESPACE index d98bc0cb..32857be9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -48,6 +48,10 @@ export(HLtest) export(Kway) export(LRstats) export(Summarise) +export(as_array) +export(as_caseform) +export(as_freqform) +export(as_table) export(assoc_graph) export(blogits) export(center3d) @@ -87,6 +91,7 @@ importFrom(MASS,loglm) importFrom(ca,cacoord) importFrom(ca,multilines) importFrom(dplyr,all_of) +importFrom(dplyr,as_tibble) importFrom(dplyr,everything) importFrom(gnm,meanResiduals) importFrom(grDevices,col2rgb) @@ -106,6 +111,7 @@ importFrom(grid,seekViewport) importFrom(grid,unit) importFrom(grid,upViewport) importFrom(grid,viewport) +importFrom(methods,is) importFrom(rgl,translate3d) importFrom(stats,as.formula) importFrom(stats,chisq.test) diff --git a/R/as_array.R b/R/as_array.R new file mode 100644 index 00000000..09481c1d --- /dev/null +++ b/R/as_array.R @@ -0,0 +1,46 @@ +#' Convert frequency, case, or table form data into an array +#' +#' Converts object (`obj`) in frequency, case or table form into an array. The +#' column containing the frequencies (`freq`) must be supplied if `obj` is in +#' frequency form. +#' +#' @param obj object to be converted to an array +#' @param freq If `obj` is in frequency form, this is the name of the frequency column. Leave as `NULL` if `obj` is in any other form. +#' @param dims A character vector of dimensions. If not specified, all variables apart from `freq` will be used as dimensions +#' @return object in array form +#' +#' @details +#' Unclasses the \code{as_table()} function to return an object in array form. +#' +#' @author Gavin M. Klorfine +#' +#' @examples +#' library(vcdExtra) +#' +#' data("HairEyeColor") +#' +#' freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +#' tidy_freqForm <- dplyr::as_tibble(HairEyeColor) # Generate tidy frequency form data +#' caseForm <- expand.dft(freqForm) # Generate case form data +#' +#' # Frequency form -> array form +#' as_array(freqForm, freq = "Freq") |> str() +#' +#' # Warned if forgot to specify freq +#' as_array(freqForm) |> str() +#' +#' # Case form -> array form +#' as_array(caseForm) |> str() +#' +#' # Frequency (tibble) form -> array form +#' as_array(tidy_freqForm, freq = "n") |> str() +#' +#' # For specific dimensions +#' as_array(tidy_freqForm, freq = "n", dims = c("Hair", "Eye")) |> str() +#' +#' +#' @export + +as_array <- function(obj, freq = NULL, dims = NULL){ + return(unclass(as_table(obj, freq, dims))) # Unclass as_table output +} \ No newline at end of file diff --git a/R/as_caseform.R b/R/as_caseform.R new file mode 100644 index 00000000..a9344a28 --- /dev/null +++ b/R/as_caseform.R @@ -0,0 +1,58 @@ +#' Convert frequency or table form into case form. +#' +#' Converts object (`obj`) in frequency or table form into case form. The +#' column containing the frequencies (`freq`) must be supplied if `obj` is in +#' frequency form. Returns a tibble if `tidy` is set to `TRUE`. +#' +#' @param obj object to be converted to case form +#' @param freq If `obj` is in frequency form, this is the name of the frequency column. If `obj` is in any other form, do not supply an argument (see "Details") +#' @param dims A character vector of dimensions. If not specified, all variables apart from `freq` will be used as dimensions +#' @param tidy returns a tibble if set to TRUE +#' @return object in case form. +#' +#' @details +#' A wrapper for \code{expand.dft()} that is able to handle arrays. +#' +#' If a frequency column is not supplied, this function defaults to "Freq" +#' just like \code{expand.dft()}. Converts `obj` to a table using +#' \code{as_table()} before converting to case form. +#' +#' @author Gavin M. Klorfine +#' +#' @importFrom dplyr as_tibble +#' +#' @examples +#' library(vcdExtra) +#' +#' data("HairEyeColor") +#' +#' freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +#' tidy_freqForm <- dplyr::as_tibble(HairEyeColor) # Generate tidy frequency form data +#' tableForm <- as_table(HairEyeColor) # Generate table form data +#' arrayDat <- as_array(HairEyeColor) # Generate an array +#' +#' # Frequency form -> case form +#' as_caseform(freqForm) |> str() +#' +#' # Frequency form (tibble) -> case form +#' as_caseform(tidy_freqForm, freq = "n") |> str() +#' +#' # Array -> case form +#' as_caseform(arrayDat) |> str() +#' +#' # Optionally specify dims +#' as_caseform(tableForm, dims = c("Hair", "Eye")) |> str() +#' +#' +#' @export + +as_caseform <- function(obj, freq = "Freq", dims = NULL, tidy = TRUE){ + + tab <- expand.dft(as_table(obj, freq = freq, dims = dims), freq = freq) + + if (tidy){ + tab <- dplyr::as_tibble(tab) + } + + return(tab) +} \ No newline at end of file diff --git a/R/as_freqform.R b/R/as_freqform.R new file mode 100644 index 00000000..a9449612 --- /dev/null +++ b/R/as_freqform.R @@ -0,0 +1,59 @@ +#' Convert any form (case or table form) into frequency form. +#' +#' A wrapper for \code{as.data.frame()} that is able to properly handle arrays. +#' Converts object (`obj`) in case or table form into frequency form. The +#' column containing the frequencies (`freq`) must be supplied if `obj` is +#' already in frequency form (and you are using this function to select +#' dimensions). Returns a tibble if `tidy` is set to `TRUE`. +#' +#' @param obj object to be converted to frequency form +#' @param freq If `obj` is already in frequency form, this is the name of the frequency column. If `obj` is in any other form, do not supply an argument (see "Details") +#' @param dims A character vector of dimensions. If not specified, all variables apart from `freq` will be used as dimensions +#' @param tidy returns a tibble if set to TRUE +#' @return object in frequency form. +#' +#' @details +#' Converts `obj` to a table using \code{as_table()} before converting to +#' frequency form +#' +#' @author Gavin M. Klorfine +#' +#' @importFrom dplyr as_tibble +#' +#' @examples +#' library(vcdExtra) +#' +#' data("HairEyeColor") +#' +#' freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +#' tableForm <- as_table(HairEyeColor) # Generate table form data +#' arrayDat <- as_array(HairEyeColor) # Generate an array +#' caseForm <- as_caseform(HairEyeColor) # Generate case form data +#' +#' # array -> frequency form +#' as_freqform(arrayDat) |> str() +#' +#' # table -> frequency form +#' as_freqform(tableForm) |> str() +#' +#' # case -> frequency form +#' as_freqform(caseForm) |> str() +#' +#' # Selecting dimensions (optional) +#' as_freqform(freqForm, freq = "Freq", dims = c("Hair", "Eye")) |> str() +#' +#' as_freqform(tableForm, dims = c("Hair", "Eye")) |> str() +#' +#' +#' @export + +as_freqform <- function(obj, freq = NULL, dims = NULL, tidy = TRUE){ + + tab <- as.data.frame(as_table(obj, freq = freq, dims = dims)) + + if (tidy){ + tab <- dplyr::as_tibble(tab) + } + + return(tab) +} \ No newline at end of file diff --git a/R/as_table.R b/R/as_table.R new file mode 100644 index 00000000..369adaf2 --- /dev/null +++ b/R/as_table.R @@ -0,0 +1,152 @@ +#' Convert frequency or case form data into table form +#' +#' Converts object (`obj`) in frequency or case form into table form. The +#' column containing the frequencies (`freq`) must be supplied if `obj` is in +#' frequency form. Optionally returns a table of proportions with (optionally) specified margins. +#' +#' @param obj object to be converted to table form +#' @param freq If `obj` is in frequency form, this is the name of the frequency column. Leave as `NULL` if `obj` is in any other form. +#' @param dims A character vector of dimensions. If not specified, all variables apart from `freq` will be used as dimensions +#' @param prop If set to TRUE, returns a table of proportions. May also be set to a character or numeric vector of margins. +#' @return object in table form +#' +#' @details +#' If `obj` was in table form to begin with, it is returned to the user as-is +#' unless dimensions were specified (in which case it returns a table with +#' entries summed over excluded dimensions). When `prop` is set to `TRUE`, the +#' returned table will have proportions that sum to one, whereas if a character +#' or numerical vector of table dimensions is supplied to `prop`, proportions +#' will be marginalized across the specified dimensions. +#' +#' @author Gavin M. Klorfine +#' +#' @importFrom stats reformulate xtabs +#' @importFrom methods is +#' +#' @examples +#' library(vcdExtra) +#' +#' data("HairEyeColor") +#' +#' freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +#' tidy_freqForm <- dplyr::as_tibble(HairEyeColor) # Generate tidy frequency form data +#' caseForm <- expand.dft(freqForm) # Generate case form data +#' +#' # Frequency form -> table form +#' as_table(freqForm, freq = "Freq") |> str() +#' +#' # Warned if forgot to specify freq +#' as_table(freqForm) |> str() +#' +#' # Frequency form (tibble) -> table form +#' as_table(tidy_freqForm, freq = "n") |> str() +#' +#' # Case form -> table form +#' as_table(caseForm) |> str() +#' +#' # For specific dimensions +#' as_table(tidy_freqForm, freq = "n", dims = c("Hair", "Eye")) |> str() +#' +#' #-----For proportions-----# +#' +#' as_table(freqForm, freq = "Freq", prop = TRUE) |> head(c(4,4,1)) # print only Sex == Male rows +#' +#' # Marginalize proportions along "Sex" (i.e., male proportions sum to 1, female proportions sum to 1) +#' as_table(freqForm, freq = "Freq", prop = "Sex") |> head(c(4,4,1)) +#' +#' as_table(freqForm, freq = "Freq", prop = 3) |> head(c(4,4,1)) # Same as above +#' +#' # Marginalize proportions along multiple variables +#' as_table(freqForm, freq = "Freq", prop = c("Hair", "Sex")) |> head(c(4,4,1)) +#' +#' as_table(freqForm, freq = "Freq", prop = c(1, 3)) |> head(c(4,4,1)) # Same as above +#' +#' # Using dims and prop arguments in tandem +#' as_table(freqForm, freq = "Freq", dims = c("Hair", "Eye"), prop = TRUE) +#' +#' +#' @export + +as_table <- function(obj, freq = NULL, dims = NULL, prop = NULL){ + + # If user supplied a table or array, remember that + tab_or_array <- FALSE + if (is(obj, "table") || is(obj, "array")){ + + tab <- as.table(obj) # Handle arrays + + # To include dimensions if specified + if (!is.null(dims)){ + tab <- margin.table(tab, margin = dims) + } + + tab_or_array <- TRUE + } + # If obj is a tibble, convert to data frame + else if (is(obj, "table")){ + obj <- as.data.frame(obj) + } + + if (!is.null(dims)){ # If dims supplied by user, use those + cols <- dims + } + else { # If dims NOT supplied by user, use everything else + cols <- colnames(obj) + } + + if (!tab_or_array){ # If not a table or array... + if (!is.null(freq)){ # If freq supplied by user, then... (freq form) + cols <- cols[cols != freq] # Remove freq column + tab <- xtabs(reformulate(cols, response = freq), data = obj) # freq ~ cols + } + else if (is.null(freq)){ # If freq NOT supplied by user, and not array, then... (case form) + tab <- xtabs(reformulate(cols), data = obj) + + # Check if user forgot to supply freq, warn if they potentially forgot + common <- c("n", "freq", "frequency", "count") + if (length(intersect(tolower(colnames(obj)), common)) > 0){ + warning("Ensure a value for 'freq' was supplied if your data was in frequency form.") + } + } + } + + + if (!is.null(prop)){ # If user wants proportions + + if (is(prop, "logical") && prop == TRUE){ # If margins not specified + tab <- prop.table(tab) + } + else if (is.character(prop) || is.numeric(prop)){ # If proportions are to be marginal + + ### Make sure margins are not problematic ### + if (length(prop) > length(dim(tab))){ # Raise error if # of margin dims exceeds actual # of dims + stop("Number of specified margins in `prop` exceeds number of dims in table.") + } + if (length(unique(prop)) != length(prop)){ # Make sure prop margins are unique + stop("`prop` margins are not unique (i.e., a duplicate was provided).") + } + # If character vector for proportion margins, make sure margins in prop are a subset of dims in table + if (is.character(prop) && length(prop) != length(intersect(prop, names(dimnames(tab))))){ + stop("Ensure all margins specified in `prop` are dims in the table.") + } + # If numeric vector for proportion margins, + else if(is.numeric(prop)){ + if (!all(prop > 0) || !all(prop %% 1 == 0)){ # Make sure margins in prop are positive, whole nums + stop("Ensure all margins specified in `prop` are positive whole numbers.") + } + if (!all(prop <= length(dim(tab)))){ # Make sure margins in prop do not exceed # of dims in table + stop("Ensure all margins specified in `prop` do not exceed the total number of dims in the table.") + } + } + ### + + tab <- prop.table(tab, margin = prop) + } + else{ # If prop not TRUE or a numeric / character vector + stop("Argument `prop` must be supplied with either a numeric or character vector") + } + } + + + return(tab) +} \ No newline at end of file diff --git a/_pkgdown.yml b/_pkgdown.yml index 801b4966..3cdd9a1b 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -141,4 +141,13 @@ reference: - Vietnam - Vote1980 - WorkerSat - - Yamaguchi87 + - Yamaguchi87 + + - title: Conversions + desc: converting between table, freq, case, array forms + contents: + - as_table + - as_array + - as_freqform + - as_caseform + diff --git a/man/as_array.Rd b/man/as_array.Rd new file mode 100644 index 00000000..49c8814b --- /dev/null +++ b/man/as_array.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_array.R +\name{as_array} +\alias{as_array} +\title{Convert frequency, case, or table form data into an array} +\usage{ +as_array(obj, freq = NULL, dims = NULL) +} +\arguments{ +\item{obj}{object to be converted to an array} + +\item{freq}{If \code{obj} is in frequency form, this is the name of the frequency column. Leave as \code{NULL} if \code{obj} is in any other form.} + +\item{dims}{A character vector of dimensions. If not specified, all variables apart from \code{freq} will be used as dimensions} +} +\value{ +object in array form +} +\description{ +Converts object (\code{obj}) in frequency, case or table form into an array. The +column containing the frequencies (\code{freq}) must be supplied if \code{obj} is in +frequency form. +} +\details{ +Unclasses the \code{as_table()} function to return an object in array form. +} +\examples{ +library(vcdExtra) + +data("HairEyeColor") + +freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +tidy_freqForm <- dplyr::as_tibble(HairEyeColor) # Generate tidy frequency form data +caseForm <- expand.dft(freqForm) # Generate case form data + +# Frequency form -> array form +as_array(freqForm, freq = "Freq") |> str() + +# Warned if forgot to specify freq +as_array(freqForm) |> str() + +# Case form -> array form +as_array(caseForm) |> str() + +# Frequency (tibble) form -> array form +as_array(tidy_freqForm, freq = "n") |> str() + +# For specific dimensions +as_array(tidy_freqForm, freq = "n", dims = c("Hair", "Eye")) |> str() + + +} +\author{ +Gavin M. Klorfine +} diff --git a/man/as_caseform.Rd b/man/as_caseform.Rd new file mode 100644 index 00000000..b82e8790 --- /dev/null +++ b/man/as_caseform.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_caseform.R +\name{as_caseform} +\alias{as_caseform} +\title{Convert frequency or table form into case form.} +\usage{ +as_caseform(obj, freq = "Freq", dims = NULL, tidy = TRUE) +} +\arguments{ +\item{obj}{object to be converted to case form} + +\item{freq}{If \code{obj} is in frequency form, this is the name of the frequency column. If \code{obj} is in any other form, do not supply an argument (see "Details")} + +\item{dims}{A character vector of dimensions. If not specified, all variables apart from \code{freq} will be used as dimensions} + +\item{tidy}{returns a tibble if set to TRUE} +} +\value{ +object in case form. +} +\description{ +Converts object (\code{obj}) in frequency or table form into case form. The +column containing the frequencies (\code{freq}) must be supplied if \code{obj} is in +frequency form. Returns a tibble if \code{tidy} is set to \code{TRUE}. +} +\details{ +A wrapper for \code{expand.dft()} that is able to handle arrays. + +If a frequency column is not supplied, this function defaults to "Freq" +just like \code{expand.dft()}. Converts \code{obj} to a table using +\code{as_table()} before converting to case form. +} +\examples{ +library(vcdExtra) + +data("HairEyeColor") + +freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +tidy_freqForm <- dplyr::as_tibble(HairEyeColor) # Generate tidy frequency form data +tableForm <- as_table(HairEyeColor) # Generate table form data +arrayDat <- as_array(HairEyeColor) # Generate an array + +# Frequency form -> case form +as_caseform(freqForm) |> str() + +# Frequency form (tibble) -> case form +as_caseform(tidy_freqForm, freq = "n") |> str() + +# Array -> case form +as_caseform(arrayDat) |> str() + +# Optionally specify dims +as_caseform(tableForm, dims = c("Hair", "Eye")) |> str() + + +} +\author{ +Gavin M. Klorfine +} diff --git a/man/as_freqform.Rd b/man/as_freqform.Rd new file mode 100644 index 00000000..5528babd --- /dev/null +++ b/man/as_freqform.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_freqform.R +\name{as_freqform} +\alias{as_freqform} +\title{Convert any form (case or table form) into frequency form.} +\usage{ +as_freqform(obj, freq = NULL, dims = NULL, tidy = TRUE) +} +\arguments{ +\item{obj}{object to be converted to frequency form} + +\item{freq}{If \code{obj} is already in frequency form, this is the name of the frequency column. If \code{obj} is in any other form, do not supply an argument (see "Details")} + +\item{dims}{A character vector of dimensions. If not specified, all variables apart from \code{freq} will be used as dimensions} + +\item{tidy}{returns a tibble if set to TRUE} +} +\value{ +object in frequency form. +} +\description{ +A wrapper for \code{as.data.frame()} that is able to properly handle arrays. +Converts object (\code{obj}) in case or table form into frequency form. The +column containing the frequencies (\code{freq}) must be supplied if \code{obj} is +already in frequency form (and you are using this function to select +dimensions). Returns a tibble if \code{tidy} is set to \code{TRUE}. +} +\details{ +Converts \code{obj} to a table using \code{as_table()} before converting to +frequency form +} +\examples{ +library(vcdExtra) + +data("HairEyeColor") + +freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +tableForm <- as_table(HairEyeColor) # Generate table form data +arrayDat <- as_array(HairEyeColor) # Generate an array +caseForm <- as_caseform(HairEyeColor) # Generate case form data + +# array -> frequency form +as_freqform(arrayDat) |> str() + +# table -> frequency form +as_freqform(tableForm) |> str() + +# case -> frequency form +as_freqform(caseForm) |> str() + +# Selecting dimensions (optional) +as_freqform(freqForm, freq = "Freq", dims = c("Hair", "Eye")) |> str() + +as_freqform(tableForm, dims = c("Hair", "Eye")) |> str() + + +} +\author{ +Gavin M. Klorfine +} diff --git a/man/as_table.Rd b/man/as_table.Rd new file mode 100644 index 00000000..ec092718 --- /dev/null +++ b/man/as_table.Rd @@ -0,0 +1,79 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_table.R +\name{as_table} +\alias{as_table} +\title{Convert frequency or case form data into table form} +\usage{ +as_table(obj, freq = NULL, dims = NULL, prop = NULL) +} +\arguments{ +\item{obj}{object to be converted to table form} + +\item{freq}{If \code{obj} is in frequency form, this is the name of the frequency column. Leave as \code{NULL} if \code{obj} is in any other form.} + +\item{dims}{A character vector of dimensions. If not specified, all variables apart from \code{freq} will be used as dimensions} + +\item{prop}{If set to TRUE, returns a table of proportions. May also be set to a character or numeric vector of margins.} +} +\value{ +object in table form +} +\description{ +Converts object (\code{obj}) in frequency or case form into table form. The +column containing the frequencies (\code{freq}) must be supplied if \code{obj} is in +frequency form. Optionally returns a table of proportions with (optionally) specified margins. +} +\details{ +If \code{obj} was in table form to begin with, it is returned to the user as-is +unless dimensions were specified (in which case it returns a table with +entries summed over excluded dimensions). When \code{prop} is set to \code{TRUE}, the +returned table will have proportions that sum to one, whereas if a character +or numerical vector of table dimensions is supplied to \code{prop}, proportions +will be marginalized across the specified dimensions. +} +\examples{ +library(vcdExtra) + +data("HairEyeColor") + +freqForm <- as.data.frame(HairEyeColor) # Generate frequency form data +tidy_freqForm <- dplyr::as_tibble(HairEyeColor) # Generate tidy frequency form data +caseForm <- expand.dft(freqForm) # Generate case form data + +# Frequency form -> table form +as_table(freqForm, freq = "Freq") |> str() + +# Warned if forgot to specify freq +as_table(freqForm) |> str() + +# Frequency form (tibble) -> table form +as_table(tidy_freqForm, freq = "n") |> str() + +# Case form -> table form +as_table(caseForm) |> str() + +# For specific dimensions +as_table(tidy_freqForm, freq = "n", dims = c("Hair", "Eye")) |> str() + +#-----For proportions-----# + +as_table(freqForm, freq = "Freq", prop = TRUE) |> head(c(4,4,1)) # print only Sex == Male rows + +# Marginalize proportions along "Sex" (i.e., male proportions sum to 1, female proportions sum to 1) +as_table(freqForm, freq = "Freq", prop = "Sex") |> head(c(4,4,1)) + +as_table(freqForm, freq = "Freq", prop = 3) |> head(c(4,4,1)) # Same as above + +# Marginalize proportions along multiple variables +as_table(freqForm, freq = "Freq", prop = c("Hair", "Sex")) |> head(c(4,4,1)) + +as_table(freqForm, freq = "Freq", prop = c(1, 3)) |> head(c(4,4,1)) # Same as above + +# Using dims and prop arguments in tandem +as_table(freqForm, freq = "Freq", dims = c("Hair", "Eye"), prop = TRUE) + + +} +\author{ +Gavin M. Klorfine +} diff --git a/tests/testthat/test-as_table.R b/tests/testthat/test-as_table.R new file mode 100644 index 00000000..78a92aa0 --- /dev/null +++ b/tests/testthat/test-as_table.R @@ -0,0 +1,47 @@ +test_that("as_table returns table if table is supplied", { + data("HairEyeColor") + tab <- as_table(HairEyeColor) + expect_s3_class(tab, "table") +}) + +test_that("as_table returns table if array is supplied", { + data("HairEyeColor") + tab <- as_table(unclass(HairEyeColor)) # unclass() converts table -> array + expect_s3_class(tab, "table") +}) + +test_that("as_table returns table if freqform is supplied", { + data("HairEyeColor") + tab <- as_table(as.data.frame(HairEyeColor), freq = "Freq") + expect_s3_class(tab, "table") +}) + +test_that("as_table returns table if case form is supplied", { + data("HairEyeColor") + tab <- as_table(expand.dft(HairEyeColor)) + expect_s3_class(tab, "table") +}) + +test_that("as_table does not modify table entries", { + data("HairEyeColor") + tab <- as_table(HairEyeColor) + tab_freq <- as_table(as.data.frame(HairEyeColor), freq = "Freq") + tab_case <- as_table(expand.dft(HairEyeColor)) + expect_equal(sum(tab), sum(HairEyeColor)) + expect_equal(sum(tab_freq), sum(tab_case)) + expect_equal(sum(tab), sum(tab_case)) +}) + +test_that("Proportions sum to one", { + data("HairEyeColor") + tab <- as_table(HairEyeColor, prop = TRUE) + expect_equal(sum(tab), 1) +}) + +test_that("Marginal proportions sum to one", { + data("HairEyeColor") + tab <- as_table(HairEyeColor, prop = c("Hair", "Sex")) + expect_equal(sum(tab["Black",,"Male"]), 1) + tab <- as_table(HairEyeColor, prop = "Hair") + expect_equal(sum(tab["Black",,]), 1) +})