Nothing
#' @title Check whether two factors are crossed or nested
#' @name is_crossed
#' @description These functions checks whether two factors are (fully) crossed
#' or nested, i.e. if each level of one factor occurs in combination with
#' each level of the other factor (\code{is_crossed()}) resp. if each
#' category of the first factor co-occurs with only one category of the
#' other (\code{is_nested()}). \code{is_cross_classified()} checks if one
#' factor level occurs in some, but not all levels of another factor.
#'
#' @param f1 Numeric vector or \code{\link{factor}}.
#' @param f2 Numeric vector or \code{\link{factor}}.
#'
#' @return Logical. For \code{is_crossed()}, \code{TRUE} if factors are (fully)
#' crossed, \code{FALSE} otherwise. For \code{is_nested()}, \code{TRUE} if
#' factors are nested, \code{FALSE} otherwise. For \code{is_cross_classified()},
#' \code{TRUE}, if one factor level occurs in some, but not all levels of
#' another factor.
#'
#' @note If factors are nested, a message is displayed to tell whether \code{f1}
#' is nested within \code{f2} or vice versa.
#'
#' @references Grace, K. The Difference Between Crossed and Nested Factors. \href{https://www.theanalysisfactor.com/the-difference-between-crossed-and-nested-factors/}{(web)}
#'
#' @examples
#' # crossed factors, each category of
#' # x appears in each category of y
#' x <- c(1,4,3,2,3,2,1,4)
#' y <- c(1,1,1,2,2,1,2,2)
#' # show distribution
#' table(x, y)
#' # check if crossed
#' is_crossed(x, y)
#'
#' # not crossed factors
#' x <- c(1,4,3,2,3,2,1,4)
#' y <- c(1,1,1,2,1,1,2,2)
#' # show distribution
#' table(x, y)
#' # check if crossed
#' is_crossed(x, y)
#'
#'
#' # nested factors, each category of
#' # x appears in one category of y
#' x <- c(1,2,3,4,5,6,7,8,9)
#' y <- c(1,1,1,2,2,2,3,3,3)
#' # show distribution
#' table(x, y)
#' # check if nested
#' is_nested(x, y)
#' is_nested(y, x)
#'
#' # not nested factors
#' x <- c(1,2,3,4,5,6,7,8,9,1,2)
#' y <- c(1,1,1,2,2,2,3,3,3,2,3)
#' # show distribution
#' table(x, y)
#' # check if nested
#' is_nested(x, y)
#' is_nested(y, x)
#'
#' # also not fully crossed
#' is_crossed(x, y)
#'
#' # but partially crossed
#' is_cross_classified(x, y)
#'
#' @export
is_crossed <- function(f1, f2) {
tab <- table(f1, f2)
# for crossed factors, we should have no zeros in any rows
# (i.e. each level of f1 also contains any level of f2)
!any(apply(tab, 1, function(x) any(x == 0)) == TRUE)
}
#' @rdname is_crossed
#' @export
is_nested <- function(f1, f2) {
tab <- table(f1, f2)
# cross tabulation of nested factors should have only 1 value per row
# (or column) that is not zero. If we found more, factors are not nested
# or rows and columns have to be swapped.
# check if f1 is nested within f2
nested <- !any(apply(tab, 1, function(x) sum(x != 0) > 1))
if (nested) message("'f1' is nested within 'f2'")
# swap rows and columns to check whether factors are nested
# check whether f2 is nested within f1
if (!nested) {
nested <- !any(apply(tab, 2, function(x) sum(x != 0) > 1))
if (nested) message("'f2' is nested within 'f1'")
}
nested
}
#' @rdname is_crossed
#' @export
is_cross_classified <- function(f1, f2) {
suppressMessages(!is_nested(f1, f2) && !is_crossed(f1, f2))
}
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.