Skip to content

Commit

Permalink
add cj_table() function
Browse files Browse the repository at this point in the history
  • Loading branch information
leeper committed Jul 10, 2018
1 parent 5f7684f commit d16bfd6
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 15 deletions.
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Package: cregg
Type: Package
Title: Simple Conjoint Analyses and Visualization
Version: 0.2.2
Title: Simple Conjoint Tidying, Analysis, and Visualization
Version: 0.2.3
Date: 2018-07-10
Authors@R: c(person("Thomas J.", "Leeper", role = c("aut", "cre"),
email = "[email protected]",
comment = c(ORCID = "0000-0003-4097-6326")))
Description: Simple analyses of fully randomized conjoint (factorial) experiments, including estimation and visualization of average marginal component effects ('AMCEs') and marginal means ('MMs') for weighted and un-weighted survey data, reference category diagnostics, and statistical tests. Estimation of AMCEs is based upon methods described by Hainmueller, Hopkins, and Yamamoto (2014) <doi:10.1093/pan/mpt024>.
Description: Simple tidying, analysis, and visualization of conjoint (factorial) experiments, including estimation and visualization of average marginal component effects ('AMCEs') and marginal means ('MMs') for weighted and un-weighted survey data, along with useful reference category diagnostics and statistical tests. Estimation of AMCEs is based upon methods described by Hainmueller, Hopkins, and Yamamoto (2014) <doi:10.1093/pan/mpt024>.
License: MIT + file LICENSE
URL: https://github.com/leeper/cregg
BugReports: https://github.com/leeper/cregg/issues
Expand Down
5 changes: 3 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ export(amce_diffs)
export(cj)
export(cj_anova)
export(cj_df)
export(cj_freqs)
export(cj_props)
export(cj_table)
export(cj_tidy)
export(freqs)
export(mm)
export(mm_diffs)
export(props)
import(ggplot2)
import(scales)
import(stats)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# cregg 0.2.3

* Added function `cj_table()`, which can be useful in communicating the set of features and levels used in the design as a data frame (e.g,. using `knitr::kable(cj_table(data, ~ feat1 + feat2))`).
* Renamed functions `props()` -> `cj_props()` and `freqs()` to `cj_freqs()` for API consistency.

# cregg 0.2.2

* Added function `cj_df()`, which provides a modified data frame class ("cj_df") that preserves variable "label" attributes when subsetting.
Expand Down
42 changes: 42 additions & 0 deletions R/cj_table.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#' @rdname cj_freqs
#' @export
cj_table <-
function(
data,
formula,
feature_order = NULL,
feature_labels = NULL,
level_order = c("ascending", "descending"),
include_reference = FALSE,
...
) {

# get RHS variables, variable labels, and factor levels
RHS <- all.vars(stats::update(formula, 0 ~ . ))

# process feature_order argument
feature_order <- check_feature_order(feature_order, RHS)

# set level_order (within features) to ascending or descending
level_order <- match.arg(level_order)

# function to produce "fancy" feature labels
feature_labels <- clean_feature_labels(data = data, RHS = RHS, feature_labels = feature_labels)

# convert feature labels and levels to data frame
out <- make_term_labels_df(data, feature_names = feature_order, level_order = level_order)
out[["level"]] <- factor(out[["level"]], levels = out[["level"]])
out[["feature"]] <- factor(out[["feature"]],
levels = feature_order,
labels = feature_labels[feature_order])
rownames(out) <- seq_len(nrow(out))

if (isTRUE(include_reference)) {
out[["reference"]] <- FALSE
# identify reference categories
reference_categories <- unlist(lapply(data[RHS], function(x) levels(x)[1L]))
out[["reference"]][out[["level"]] %in% reference_categories] <- TRUE
}

return(out)
}
8 changes: 4 additions & 4 deletions R/package-cregg.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
#' @param formula A formula specifying a model to be estimated. All variables should be factors. For \code{estimate = "amce"} in a constrained conjoint design, two-way interactions can be specified to handle constraints between factors in the design. These are detected automatically. Higher-order constraints are not allowed and interactions are ignored for all other values of \code{estimate} as constraints are irrelevant to those statistics.
#' @param id An RHS formula specifying a variable holding respondent identifiers, to be used for clustering standard errors.
#' @param weights An (optional) RHS formula specifying a variable holding survey weights.
#' @param estimate A character string specifying an estimate type. Current options are average marginal component effects (or AMCEs, \dQuote{amce}, estimated via \code{\link{amce}}), display frequencies (\dQuote{frequncies}, estimated via \code{\link{freqs}}), marginal means (or AMMs, \dQuote{mm}, estimated via \code{\link{mm}}), differences in MMs (\dQuote{mm_differences}, via \code{\link{mm_diffs}}), or differences in AMCEs (\dQuote{amce_differences}, via \code{\link{amce_diffs}}). Additional options may be made available in the future. Non-ambiguous abbreviations are allowed.
#' @param estimate A character string specifying an estimate type. Current options are average marginal component effects (or AMCEs, \dQuote{amce}, estimated via \code{\link{amce}}), display frequencies (\dQuote{frequncies}, estimated via \code{\link{cj_freqs}}), marginal means (or AMMs, \dQuote{mm}, estimated via \code{\link{mm}}), differences in MMs (\dQuote{mm_differences}, via \code{\link{mm_diffs}}), or differences in AMCEs (\dQuote{amce_differences}, via \code{\link{amce_diffs}}). Additional options may be made available in the future. Non-ambiguous abbreviations are allowed.
#' @template feature_order
#' @template feature_labels
#' @template level_order
#' @param by A formula containing only RHS variables, specifying grouping factors over which to perform estimation.
#' @param \dots Additional arguments to \code{\link{amce}}, \code{\link{freqs}}, \code{\link{mm}}, \code{\link{mm_diffs}}, or \code{\link{amce_diffs}}.
#' @param \dots Additional arguments to \code{\link{amce}}, \code{\link{cj_freqs}}, \code{\link{mm}}, \code{\link{mm_diffs}}, or \code{\link{amce_diffs}}.
#' @author Thomas J. Leeper <[email protected]>
#' @details The main function \code{cj} is a convenience function wrapper around the underlying estimation functions that provide for average marginal component effects (AMCEs), by default, via the \code{\link{amce}} function, marginal means (MMs) via the \code{\link{mm}} function, and display frequencies via \code{\link{freqs}} and \code{\link{props}}. Additional estimands may be supported in the future through their own functions and through the \code{cj} interface. Plotting is provided via ggplot2 for all types of estimates.
#' @details The main function \code{cj} is a convenience function wrapper around the underlying estimation functions that provide for average marginal component effects (AMCEs), by default, via the \code{\link{amce}} function, marginal means (MMs) via the \code{\link{mm}} function, and display frequencies via \code{\link{cj_freqs}} and \code{\link{cj_props}}. Additional estimands may be supported in the future through their own functions and through the \code{cj} interface. Plotting is provided via ggplot2 for all types of estimates.
#'
#' The only additional functionality provided by \code{cj} over the underlying functions is the \code{by} argument, which will perform operations on subsets of \code{data}, returning a single data frame. This can be useful, for example, for evaluating profile spillover effects and subgroup results, or in any situation where one might be inclined to use a \code{for} loop or \code{lapply}, calling \code{cj} repeatedly on subgroups.
#'
Expand Down Expand Up @@ -66,7 +66,7 @@
#' plot(x, group = "ethnosplit", vline = 0.5)
#' }
#' @seealso
#' Functions: \code{\link{amce}}, \code{\link{mm}}, \code{\link{freqs}}, \code{\link{mm_diffs}}, \code{\link{plot.cj_amce}}, \code{\link{cj_tidy}}
#' Functions: \code{\link{amce}}, \code{\link{mm}}, \code{\link{cj_freqs}}, \code{\link{mm_diffs}}, \code{\link{plot.cj_amce}}, \code{\link{cj_tidy}}
#' Data: \code{\link{immigration}}, \code{\link{taxes}}
#' @keywords package
NULL
17 changes: 11 additions & 6 deletions tests/testthat/tests-classes.R
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,20 @@ test_that("mm_diffs() works", {
expect_error(mm_diffs(immigration, ~ LanguageSkills, by = ~ Gender, id = ~ CaseID), label = "mm_diffs() fails w/o LHS variable in formula")
})

test_that("freqs() works", {
expect_true(inherits(x <- freqs(immigration, ~ Gender, id = ~ CaseID), "cj_freqs"))
test_that("cj_table() works", {
expect_true(inherits(cj_table(immigration, ~ Gender + Education), "data.frame"))
expect_true("reference" %in% names(cj_table(immigration, ~ Gender + Education, include_reference = TRUE)))
})

test_that("cj_freqs() works", {
expect_true(inherits(x <- cj_freqs(immigration, ~ Gender, id = ~ CaseID), "cj_freqs"))
expect_true(inherits(plot(x), "ggplot"))
expect_true(inherits(freqs(immigration, ~ Gender, id = ~ CaseID, weights = ~ wts), "cj_freqs"), label = "freqs() works w/ 'weights'")
expect_true(inherits(cj_freqs(immigration, ~ Gender, id = ~ CaseID, weights = ~ wts), "cj_freqs"), label = "freqs() works w/ 'weights'")
})

test_that("props() works", {
expect_true(inherits(x <- props(immigration, ~ Gender, id = ~ CaseID), "cj_props"))
expect_true(inherits(props(immigration, ~ Gender, id = ~ CaseID, weights = ~ wts), "cj_props"), label = "props() works w/ 'weights'")
test_that("cj_props() works", {
expect_true(inherits(x <- cj_props(immigration, ~ Gender, id = ~ CaseID), "cj_props"))
expect_true(inherits(cj_props(immigration, ~ Gender, id = ~ CaseID, weights = ~ wts), "cj_props"), label = "props() works w/ 'weights'")
})

test_that("cj_anova() works", {
Expand Down

0 comments on commit d16bfd6

Please sign in to comment.