diff --git a/DESCRIPTION b/DESCRIPTION index d05873a2..e87820cb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,8 @@ BugReports: https://github.com/Crunch-io/crunchtabs/issues License: LGPL (>= 3) Depends: R (>= 3.5.0), - crunch + crunch, + mockery Imports: kableExtra (>= 1.1.0.9000), rlang, diff --git a/NAMESPACE b/NAMESPACE index 2373eac5..4d637469 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -46,6 +46,8 @@ export(kable_strip_rules) export(kable_strip_toprules) export(prepareExtraSummary) export(sortAliases) +export(tabBookWeightSpec_crunchtabs) +export(tabBook_crunchtabs) export(themeDefaultExcel) export(themeDefaultLatex) export(themeHuffPoCrosstabs) @@ -84,6 +86,7 @@ importFrom(crunch,values) importFrom(crunch,weight) importFrom(crunch,weightVariables) importFrom(digest,digest) +importFrom(jsonlite,fromJSON) importFrom(kableExtra,column_spec) importFrom(kableExtra,kable_styling) importFrom(magrittr,`%>%`) @@ -96,4 +99,5 @@ importFrom(stats,quantile) importFrom(stats,weighted.mean) importFrom(utils,installed.packages) importFrom(utils,modifyList) +importFrom(utils,stack) importFrom(utils,type.convert) diff --git a/R/asToplineCategoricalArray.R b/R/asToplineCategoricalArray.R index e286a266..90b05a27 100644 --- a/R/asToplineCategoricalArray.R +++ b/R/asToplineCategoricalArray.R @@ -81,7 +81,7 @@ as.ToplineCategoricalArray <- function(questions, question_alias = NULL, labels #' Given two or more waves of a categorical array question, convert them into #' categoricals for presentation in a tracking report. #' -#' +#' @export catArrayToCategoricals <- function(questions, question_alias, labels) { obj <- questions[[1]] statements <- obj$subnames diff --git a/R/codeBookSummary.R b/R/codeBookSummary.R index 58a70939..af2743f3 100644 --- a/R/codeBookSummary.R +++ b/R/codeBookSummary.R @@ -99,7 +99,8 @@ codeBookSummary.CategoricalVariable <- function(x, multiple = FALSE, ...) { #' @export codeBookSummary.MultipleResponseVariable <- function(x, ...) { responses <- list() - subvars <- names(subvariables(x)) + sv <- crunch::subvariables(x) + subvars <- names(sv) for (i in 1:length(names(x))) { responses[[i]] <- codeBookSummary(x[[i]], multiple = TRUE) } @@ -138,6 +139,7 @@ codeBookSummary.CategoricalArrayVariable <- function(x, ...) codeBookSummary.Mul #' @describeIn codeBookSummary Prepares a codeBookSummary data.frame for a NumericVariable #' @export codeBookSummary.NumericVariable <- function(x, ...) { + x <- as.vector(x) mu <- round(mean(x, na.rm = T), 2) std <- round(sd(x, na.rm = TRUE)) minima <- round(min(x, na.rm = T), 2) @@ -167,7 +169,6 @@ codeBookSummary.NumericVariable <- function(x, ...) { #' @describeIn codeBookSummary Prepares a codeBookSummary data.frame for a TextVariable #' @export codeBookSummary.TextVariable <- function(x, ...) { - filled_verbs <- as.vector(x) filled_verbs <- filled_verbs[!is.na(filled_verbs)] filled_verbs <- filled_verbs[!filled_verbs %in% c("", "__NA__")] @@ -195,6 +196,7 @@ codeBookSummary.TextVariable <- function(x, ...) { #' @describeIn codeBookSummary Prepares a codeBookSummary data.frame for a DatetimeVaraible #' @export codeBookSummary.DatetimeVariable <- function(x, ...) { + x <- as.vector(x) minima <- min(x, na.rm = T) maxima <- max(x, na.rm = T) missings <- sum(is.na(as.vector(x))) diff --git a/R/getters.R b/R/getters.R index edb16750..08f278b6 100644 --- a/R/getters.R +++ b/R/getters.R @@ -98,3 +98,17 @@ getSubNames <- function(x) { getSubAliases <- function(x) { sapply(x@.Data[[1]]$dimensions[[1]]$references$subreferences, function(xi) xi$alias) } + +#' Extract counts from a tabbook +#' @param x A results object or element +getCounts <- function(x, alias) { + +} + +#' Extract proportions from a tabbook +#' @param x A results object or element +getProportions <- function(x, alias) { + UseMethod("getProportions", x) +} + + diff --git a/R/tabBooks.R b/R/tabBooks.R index 4839ecfd..fcb36b88 100644 --- a/R/tabBooks.R +++ b/R/tabBooks.R @@ -12,28 +12,28 @@ #' @param include_original_weighted Logical, if you have specified complex weights #' should the original weighted variable be included or only the custom weighted version? tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, include_original_weighted = TRUE) { - + banner_flatten <- unique(unlist(banner, recursive = FALSE)) names(banner_flatten) <- sapply(banner_flatten, function(v) v$alias) banner_use <- banner if (topline) { banner_use$Results[[2]] <- NULL } - + multitable <- getMultitable(banner_flatten, dataset) - + if (is.null(weight) | is.null(weight(dataset))) { default_weight <- NULL } else { default_weight <- alias(weight(dataset)) } - - + + if (is.list(weight)) { tab_frame <- crunch::tabBookWeightSpec( dataset, weight, append_default_wt = include_original_weighted ) tab_frame <- tab_frame[tab_frame$alias %in% vars,] - + book <- suppressWarnings( tabBook_crunchtabs( multitable, @@ -42,11 +42,11 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl output_format = "json" ) ) - + } else { - + tab_frame <- tab_frame_generate(default_weight, vars) - + book <- suppressWarnings( tabBook_crunchtabs( multitable, @@ -55,62 +55,62 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl output_format = "json" ) ) - + } - + # Put tab_frame in vars order tab_frame <- tab_frame[ rev( order(tab_frame$alias, factor(vars, levels = vars) - ) - ), + ) + ), ] - + banner_var_names <- sapply(seq_along(book[[1]]), function(ix) { crunch::aliases(crunch::variables(book[[1]][[ix]]))[2] }) banner_var_names[1] <- "___total___" # var_nums <- seq_len(nrow(tab_frame)) var_nums <- setdiff(match(vars, crunch::aliases(book)), NA) - + structure(unlist(lapply(seq_along(var_nums), function(tab_frame_pos) { vi <- var_nums[tab_frame_pos] crunch_cube <- book[[vi]][[1]] - + ## Metadata cube_variable <- crunch::variables(crunch_cube)[1] - + if (all(is.na(tab_frame$weight))) { default_weighted <- TRUE } else { default_weighted <- tab_frame$weight[tab_frame_pos] == default_weight } - + if (default_weighted) { alias <- aliases(cube_variable) } else { alias <- paste0(aliases(cube_variable), "_", tab_frame$weight[tab_frame_pos]) } - + if (alias == "total") { alias <- tab_frame$alias[tab_frame_pos] var_type <- type(dataset[[alias]]) } else { var_type <- type(dataset[[aliases(cube_variable)]]) } - + is_mr_type <- var_type == "multiple_response" is_cat_type <- var_type %in% c("categorical", "categorical_array") is_array_type <- var_type == "categorical_array" is_toplines_array <- is_array_type && topline is_crosstabs_array <- is_array_type && !topline - - + + valiases <- valiases_tabbook_extract( is_crosstabs_array, crunch_cube, cube_variable, question_name ) - + if (!default_weighted) valiases <- paste0(valiases, "_", tab_frame$weight[tab_frame_pos]) - + subnames <- if (is_array_type) getSubNames(crunch_cube) var_cats <- categories(cube_variable[[1]]) inserts <- if (is_cat_type) { @@ -118,7 +118,7 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl collateCats(crunch::transforms(cube_variable)[[1]]$insertions, var_cats) } show_mean_median <- is_cat_type && any(!is.na(values(na.omit(var_cats)))) - + metadata <- list( name = names(cube_variable), description = crunch::descriptions(cube_variable), @@ -130,7 +130,7 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl categories = var_cats, inserts_obj = inserts[sapply(inserts, function(x) is.null(x$missing) || !x$missing)] ) - + pbook <- lapply(seq_along(book[[vi]]), function(vix) { crunch::prop.table(crunch::noTransforms(book[[vi]][[vix]]), margin = c(2, if (is_array_type) 3)) }) @@ -143,9 +143,9 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl wbbook <- lapply(seq_along(book[[vi]]), function(vix) { crunch::margin.table(crunch::noTransforms(book[[vi]][[vix]]), margin = c(2, if (is_array_type) 3)) }) - + names(pbook) <- names(bbook) <- names(cbook) <- names(wbbook) <- banner_var_names - + for (bi in banner_var_names) { if (!identical(banner_flatten[[bi]]$categories_out, banner_flatten[[bi]]$categories)) { pbook[[bi]] <- bannerDataRecode(pbook[[bi]], banner_flatten[[bi]]) @@ -154,10 +154,10 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl wbbook[[bi]] <- bannerDataRecode(wbbook[[bi]], banner_flatten[[bi]]) } } - + sapply(valiases, function(valias) { ri <- which(valiases %in% valias) - + pdata <- row_data(pbook, ri, is_crosstabs_array, is_toplines_array, FALSE) cdata <- row_data(cbook, ri, is_crosstabs_array, is_toplines_array, FALSE) bdata <- row_data(bbook, ri, is_crosstabs_array, is_toplines_array, TRUE) @@ -168,14 +168,14 @@ tabBooks <- function(dataset, vars, banner, weight = NULL, topline = FALSE, incl mddata <- lapply(cdata, function(mbook) { if (show_mean_median) { applyInsert(mbook, var_cats, calcTabMedianInsert) } }) - + if (!is_mr_type) { bdata <- lapply(bdata, function(xi) { matrix(xi, nrow = nrow(pdata[[2]]), ncol = length(xi), byrow = TRUE, dimnames = list(rownames(pdata[[2]]), names(xi))) }) } - + structure(c(alias = valias, metadata, subnumber = ri, @@ -228,14 +228,14 @@ tab_frame_generate <- function(default_weight = NULL, vars) { #' @param crunch_cube A sub-cube of a `crunch::tabBook` #' @param cube_variable A sub-cube of a `crunch::tabBook` valiases_tabbook_extract <- function(is_crosstabs_array, crunch_cube, cube_variable, question_name) { - if (is_crosstabs_array) { - valiases <- getSubAliases(crunch_cube) - } else { - valiases <- crunch::aliases(cube_variable) - if (valiases == "total") { - valiases <- question_name - } + if (is_crosstabs_array) { + valiases <- getSubAliases(crunch_cube) + } else { + valiases <- crunch::aliases(cube_variable) + if (valiases == "total") { + valiases <- question_name } + } valiases } @@ -318,7 +318,7 @@ row_data <- function(data, row, is_crosstabs_array, is_toplines_array, is_base) names(dimnames(dt)) <- NULL return(dt) }) - + if (is_crosstabs_array) { data <- lapply(data, function(xi) { if (length(dim(xi)) == 3) { @@ -363,15 +363,15 @@ compute_pvals <- function(counts, counts_unweighted) { n <- margin.table(counts) bases_adj <- counts_unweighted + 1 n_adj <- margin.table(bases_adj) - + nrows <- nrow(counts) ncols <- ncol(counts) - + R <- margin.table(counts, 1) / n C_adj <- margin.table(bases_adj, 2) / n_adj Ctbl <- prop.table(counts, margin = 2) Ctbl_adj <- prop.table(bases_adj, margin = 2) - + observed <- (Ctbl_adj * (1 - Ctbl_adj)) expected <- observed %*% C_adj d.c <- (1 - 2 * C_adj) / C_adj diff --git a/R/tabbook-additions.R b/R/tabbook-additions.R index 4d11ea1f..28b3e955 100644 --- a/R/tabbook-additions.R +++ b/R/tabbook-additions.R @@ -348,7 +348,7 @@ tabBookSingle_crunchtabs <- function( options = dots ) ## Add this after so that if it is NULL, the "where" key isn't present - body$where <- crunch:::variablesFilter(dataset) + # body$where <- crunch:::variablesFilter(dataset) if (use_legacy_endpoint) { warning( @@ -362,11 +362,11 @@ tabBookSingle_crunchtabs <- function( ## POST the query, which (after progress polling) returns a URL to download result <- crunch::crPOST(tabbook_url, config = httr::add_headers(`Accept` = accept), - body = jsonlite::toJSON(body) + body = jsonlite::toJSON(body, null = "null") ) if (is.null(file)) { ## Read in the tab book content and turn it into useful objects - out <- crunch::retry(crunch::crGET(result), wait = 0.5) #nocov + out <- crunch:::retry(crunch::crGET(result), wait = 0.5) #nocov return(crunch:::TabBookResult(out)) } else { file <- crunch::crDownload(result, file) diff --git a/man/tabBookWeightSpec_crunchtabs.Rd b/man/tabBookWeightSpec_crunchtabs.Rd new file mode 100644 index 00000000..49db6026 --- /dev/null +++ b/man/tabBookWeightSpec_crunchtabs.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tabbook-additions.R +\name{tabBookWeightSpec_crunchtabs} +\alias{tabBookWeightSpec_crunchtabs} +\title{Helper function for setting complex weights on a `tabbook`} +\usage{ +tabBookWeightSpec_crunchtabs(dataset, weights, append_default_wt = TRUE) +} +\arguments{ +\item{dataset}{A `CrunchDataset`} + +\item{weights}{A list where each item has a name that indicates the +weight's alias that should be use (no name indicates unweighted) and +each item is a vector of variable aliases to include as pages in the +`tabbook`.} + +\item{append_default_wt}{Whether to append the dataset's default weight +(or unweighted pages if no weight is set) for all variables.} +} +\value{ +A data.frame with two columns, `weight`, the alias of the weight to use, +and alias, the alias of the variable to use the weight on. If `append_default_wt` +is `TRUE`, the returned object is sorted in the order of aliases in the dataset, +and with the default weight first, followed by the weights specified in the `weights` +argument. +} +\description{ +For json [`tabBook()`], you can specify a weight per variable in the +dataset, where each row in the data.frame indicates a weight and +alias to use for each page. +} +\examples{ +\dontrun{ +ds <- newExampleDataset("pets") +mt <- newMultitable(~q1, ds) + +weight_spec <- tabBookWeightSpec( + ds, + list(wt1 = "gender", wt2 = "starttime", "gender") +) + +# Now can use the weight spec in `tabBook()` +tabbook <- tabBook(mt, ds, weight = weight_spec) +} +} diff --git a/man/tabBook_crunchtabs.Rd b/man/tabBook_crunchtabs.Rd new file mode 100644 index 00000000..7d514929 --- /dev/null +++ b/man/tabBook_crunchtabs.Rd @@ -0,0 +1,90 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tabbook-additions.R +\name{tabBook_crunchtabs} +\alias{tabBook_crunchtabs} +\title{Compute a Tab Book} +\usage{ +tabBook_crunchtabs( + multitable, + dataset, + weight = crunch::weight(dataset), + output_format = c("json", "xlsx"), + file = NULL, + filter = NULL, + use_legacy_endpoint = envOrOption("use.legacy.tabbook.endpoint", FALSE), + append_default_wt = TRUE, + ... +) +} +\arguments{ +\item{multitable}{a `Multitable` object} + +\item{dataset}{CrunchDataset, which may be subset with a filter expression +on the rows, and a selection of variables to use on the columns.} + +\item{weight}{a CrunchVariable that has been designated as a potential +weight variable for `dataset`, or `NULL` for unweighted results. +Default is the currently applied [`weight`]. Additionally, weights can be +set on a per variable basis for json export only. To do so, specify the weight +as either a list (which will be passed to `tabBookWeightSpec()`, or a data.frame +that mimics the structure. See [`tabBookWeightSpec()`] for more details.} + +\item{output_format}{character export format: currently supported values are "json" +(default) and "xlsx".} + +\item{file}{character local filename to write to. A default filename will be +generated from the `multitable`'s name if one is not supplied and the +"xlsx" format is requested. Not required for "json" format export.} + +\item{filter}{a Crunch `filter` object or a vector of names +of \code{\link{filters}} defined in the dataset.} + +\item{use_legacy_endpoint}{Logical, indicating whether to use a 'legacy' +endpoint for compatibility (this endpoint will be removed in the future). +Defaults to `FALSE`, but can be set in the function, or with the environment +variable `R_USE_LEGACY_TABBOOK_ENDPOINT` or R option +`use.legacy.tabbook.endpoint`.} + +\item{append_default_wt}{passed to [`tabBookWeightSpec()`] if `weight` is a list} + +\item{...}{Additional "options" passed to the tab book POST request. +More details can be found +[in the crunch API documentation]( +https://docs.crunch.io/endpoint-reference/endpoint-multitable.html#options) +or [for the legacy endpoint]( +https://docs.crunch.io/endpoint-reference/endpoint-tabbook.html#options)} +} +\value{ +If "json" format is requested, the function returns an object of +class `TabBookResult`, containing a list of `MultitableResult` +objects, which themselves contain `CrunchCube`s. For single weight tabbook, +the variables are always sorted in the order the server stores them in, +but complex weights are sorted in the order of the data.frame given. If +"xlsx" is requested, the function invisibly returns the filename (`file`, +if specified, or the the autogenerated file name). If you request "json" and +wish to access the JSON data underlying the `TabBookResult`, pass in a path +for `file` and you will get a JSON file written there as well. +} +\description{ +This function allows you to generate a tab book from a multitable and data. +As with other functions, you can select the rows and columns you want to +work with by subsetting the `dataset` you pass into the function. +} +\details{ +By specifying a "json" `format`, instead of generating an Excel +workbook, you'll get a TabBookResult object, containing nested CrunchCube +results. You can then further format these and construct custom tab reports. + +Tabbook pages are organized in the order the variables are stored by the +server, unless complex weights are specified, in which case, the variables +are sorted in the order of the weight specification dataset (like the +one created by `tabBookWeightSpec()`). +} +\examples{ +\dontrun{ +m <- newMultitable(~ gender + age4 + marstat, data = ds) +tabBook(m, ds, format = "xlsx", file = "wealthy-tab-book.xlsx", filter = "wealthy") +book <- tabBook(m, ds) # Returns a TabBookResult +tables <- prop.table(book, 2) +} +} diff --git a/tests/testthat.R b/tests/testthat.R index 4d22943b..10be9a80 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,4 +1,5 @@ -library(httptest) +library(testthat) +library(mockery) library(crunchtabs) test_check("crunchtabs") diff --git a/tests/testthat/Example Dataset with Nets.tex b/tests/testthat/Example Dataset with Nets.tex deleted file mode 100644 index 77a1ebe6..00000000 --- a/tests/testthat/Example Dataset with Nets.tex +++ /dev/null @@ -1,792 +0,0 @@ -\documentclass[landscape]{article} -\usepackage[pdftex]{graphicx} -\usepackage[utf8]{inputenc} -\usepackage{fancyhdr} -\usepackage{sfmath} -\usepackage{comment} -\usepackage[T1]{fontenc} -\usepackage[pdftex=true, pdftoolbar=true, pdfmenubar=true, pdfauthor = {}, pdfcreator = {PDFLaTeX}, pdftitle = {}, colorlinks=true, urlcolor=blue, linkcolor=blue, citecolor=blue, implicit=true, hypertexnames=false]{hyperref} -\usepackage[scaled]{helvet} -\renewcommand*\familydefault{\sfdefault} -\usepackage{booktabs, dcolumn, longtable} -\usepackage[top=0.6in, bottom=0.6in, left=0.5in, right=0.5in, includeheadfoot]{geometry} -\usepackage{array} -\usepackage[english]{babel} -\newcolumntype{B}[2]{>{#1\hspace{0pt}\arraybackslash}b{#2}} -\setlength{\parindent}{0pt} -\usepackage[dvipsnames]{color} -\definecolor{gray}{gray}{0.85} -\pagestyle{fancy} -\renewcommand{\headrulewidth}{0pt} -\renewcommand{\footrulewidth}{0pt} -\fancyhead{} -\fancyhead[L]{{\fontsize{16}{24}\textbf{Example Dataset with Nets}}} -\newcolumntype{d}{D{.}{.}{3.2}} -\newcolumntype{g}{D{\%}{\%}{3.0}} -\usepackage{float} -\usepackage{marginnote} -\setlength\extrarowheight{2pt} -\newlength\mywidth -\setlength\mywidth{3.5in} -\usepackage{caption} -\captionsetup[table]{labelformat=empty} -\renewcommand*{\marginfont}{\scriptsize\itshape} -\fancyfoot{} -\fancyfoot[R]{\thepage} -\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp} -\let\PBS=\PreserveBackslash -\newcommand{\longtablesep}{\endfirsthead \multicolumn{2}{c}{\textit{}} \\ \endhead \multicolumn{2}{c}{\textit{}} \\ \endfoot \endlastfoot} -\usepackage[titles]{tocloft} -\newcommand{\cftchapfont}{12} -\newcommand{\formatvardescription}[1]{#1} -\newcommand{\formatvarname}[1]{#1} -\newcommand{\formatvaralias}[1]{#1} -\newcommand{\formatvarfiltertext}[1]{\fontsize{8}{12}\textit{#1}} -\newcommand{\formatvarsubname}[1]{#1} -\usepackage{amsmath} -\newenvironment{absolutelynopagebreak} - {\par\nobreak\vfil\penalty0\vfilneg - \vtop\bgroup} - {\par\xdef\tpd{\the\prevdepth}\egroup - \prevdepth=\tpd} - - -\newcommand{\bannera}[1]{\toprule - & \multicolumn{1}{c}{\bf } & \multicolumn{2}{c}{\bf Age} & \multicolumn{2}{c}{\bf Gender} \\ \cmidrule(lr{.75em}){3-4} \cmidrule(lr{.75em}){5-6} -{\bf #1} & \multicolumn{1}{c}{Total} & \multicolumn{1}{c}{16 to 34} & \multicolumn{1}{c}{35+} & \multicolumn{1}{c}{Male} & \multicolumn{1}{c}{Female} \\ -\midrule -\endfirsthead -\toprule -& \multicolumn{5}{c}{} \\ & \multicolumn{1}{c}{\bf } & \multicolumn{2}{c}{\bf Age} & \multicolumn{2}{c}{\bf Gender} \\ \cmidrule(lr{.75em}){3-4} \cmidrule(lr{.75em}){5-6} -{\bf #1} & \multicolumn{1}{c}{Total} & \multicolumn{1}{c}{16 to 34} & \multicolumn{1}{c}{35+} & \multicolumn{1}{c}{Male} & \multicolumn{1}{c}{Female} \\ -\midrule -\endhead -\midrule -& \multicolumn{5}{c}{} \\ -\bottomrule -\endfoot -\bottomrule -\endlastfoot -} -\newcommand{\tbltopa[1]}{ -\begin{longtable}{@{\extracolsep{\fill}}>{\hangindent=1em \PBS \raggedright \hspace{0pt}}b{#1}*{5}{r}}} - -\newcommand{\bannerb}[1]{\toprule - & \multicolumn{1}{c}{\bf } & \multicolumn{3}{c}{\bf Age} \\ \cmidrule(lr{.75em}){3-5} -{\bf #1} & \multicolumn{1}{c}{Total} & \multicolumn{1}{c}{16 to 34} & \multicolumn{1}{c}{35 to 54} & \multicolumn{1}{c}{55+} \\ -\midrule -\endfirsthead -\toprule -& \multicolumn{4}{c}{} \\ & \multicolumn{1}{c}{\bf } & \multicolumn{3}{c}{\bf Age} \\ \cmidrule(lr{.75em}){3-5} -{\bf #1} & \multicolumn{1}{c}{Total} & \multicolumn{1}{c}{16 to 34} & \multicolumn{1}{c}{35 to 54} & \multicolumn{1}{c}{55+} \\ -\midrule -\endhead -\midrule -& \multicolumn{4}{c}{} \\ -\bottomrule -\endfoot -\bottomrule -\endlastfoot -} -\newcommand{\tbltopb[1]}{ -\begin{longtable}{@{\extracolsep{\fill}}>{\hangindent=1em \PBS \raggedright \hspace{0pt}}b{#1}*{4}{r}}} - -\begin{document} -\setlength{\LTleft}{0pt} -\setlength{\LTright}{\fill} -\setlength{\LTcapwidth}{\textwidth} -\vspace{.25in} - - - - -{ -%% here's where individual input starts %% - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 1. Do you have any of these animals as pets? Please select all that apply.} -\hangindent=0em \parbox{9in}{ -\formatvardescription{1. Do you have any of these animals as pets? Please select all that apply.}\\ -\formatvarfiltertext{Uniform base is True.}} \\ -\addlinespace -\bannera{} - - -Cat & 25\% & 0\% & 53\% & 46\% & 0\% \\ -Dog & 47\% & 31\% & 65\% & 28\% & 71\% \\ -Bird & 38\% & 44\% & 33\% & 28\% & 51\% \\ -\midrule -Unweighted N & \multicolumn{1}{c}{17} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{11} & \multicolumn{1}{c}{9} & \multicolumn{1}{c}{8} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -Cat & 25\% & 0\% & 100\% & 0\% \\ -Dog & 47\% & 31\% & 35\% & 100\% \\ -Bird & 38\% & 44\% & 35\% & 30\% \\ -\midrule -Unweighted N & \multicolumn{1}{c}{17} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{3} & \multicolumn{1}{c}{8} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 2. What is your favorite pet?} -\hangindent=0em \parbox{9in}{ -\formatvardescription{2. What is your favorite pet?}} \\ -\addlinespace -\bannera{} - - -\textbf{header} & & & & & \\ -Cat & 30\% & 38\% & 25\% & 18\% & 44\% \\ -\textbf{Net: Cat/Bird} & \textbf{50\%} & \textbf{38\%} & \textbf{58\%} & \textbf{30\%} & \textbf{73\%} \\ -Dog & 50\% & 62\% & 42\% & 69\% & 27\% \\ -\textbf{Net: Cat/Dog} & \textbf{80\%} & \textbf{100\%} & \textbf{67\%} & \textbf{87\%} & \textbf{71\%} \\ -Bird & 20\% & 0\% & 33\% & 12\% & 29\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 99\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{13} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{7} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -\textbf{header} & & & & \\ -Cat & 30\% & 38\% & 0\% & 69\% \\ -\textbf{Net: Cat/Bird} & \textbf{50\%} & \textbf{38\%} & \textbf{35\%} & \textbf{100\%} \\ -Dog & 50\% & 62\% & 65\% & 0\% \\ -\textbf{Net: Cat/Dog} & \textbf{80\%} & \textbf{100\%} & \textbf{65\%} & \textbf{69\%} \\ -Bird & 20\% & 0\% & 35\% & 31\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{13} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{4} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 3A. Name the kinds of pets you have at these locations. — Home} -\hangindent=0em \parbox{9in}{ -\formatvardescription{3A. Name the kinds of pets you have at these locations. — Home}} \\ -\addlinespace -\bannera{} - - -Cat & 49\% & 22\% & 66\% & 100\% & 26\% \\ -Dog & 43\% & 56\% & 34\% & 0\% & 62\% \\ -Bird & 9\% & 22\% & 0\% & 0\% & 13\% \\ -\textbf{Net: Cat/Dog} & \textbf{92\%} & \textbf{78\%} & \textbf{100\%} & \textbf{100\%} & \textbf{88\%} \\ -\midrule -Totals & 101\% & 100\% & 100\% & 100\% & 101\% \\ -Unweighted N & \multicolumn{1}{c}{11} & \multicolumn{1}{c}{3} & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{6} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -Cat & 49\% & 22\% & 100\% & 46\% \\ -Dog & 43\% & 56\% & 0\% & 54\% \\ -Bird & 9\% & 22\% & 0\% & 0\% \\ -\textbf{Net: Cat/Dog} & \textbf{92\%} & \textbf{78\%} & \textbf{100\%} & \textbf{100\%} \\ -\midrule -Totals & 101\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{11} & \multicolumn{1}{c}{3} & \multicolumn{1}{c}{2} & \multicolumn{1}{c}{6} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 3B. Name the kinds of pets you have at these locations. — Work} -\hangindent=0em \parbox{9in}{ -\formatvardescription{3B. Name the kinds of pets you have at these locations. — Work}} \\ -\addlinespace -\bannera{} - - -Cat & 42\% & 50\% & 36\% & 54\% & 18\% \\ -Dog & 37\% & 14\% & 54\% & 46\% & 18\% \\ -Bird & 21\% & 36\% & 11\% & 0\% & 64\% \\ -\textbf{Net: Cat/Dog} & \textbf{79\%} & \textbf{64\%} & \textbf{90\%} & \textbf{100\%} & \textbf{36\%} \\ -\midrule -Totals & 100\% & 100\% & 101\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{16} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{12} & \multicolumn{1}{c}{9} & \multicolumn{1}{c}{7} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -Cat & 42\% & 50\% & 21\% & 67\% \\ -Dog & 37\% & 14\% & 79\% & 0\% \\ -Bird & 21\% & 36\% & 0\% & 33\% \\ -\textbf{Net: Cat/Dog} & \textbf{79\%} & \textbf{64\%} & \textbf{100\%} & \textbf{67\%} \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{16} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{8} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 4. Number of dogs} -\hangindent=0em \parbox{9in}{ -\formatvardescription{4. Number of dogs}} \\ -\addlinespace -\bannera{} - - -0-1 & 6\% & 0\% & 12\% & 0\% & 14\% \\ -1-2 & 16\% & 0\% & 29\% & 29\% & 0\% \\ -2-3 & 31\% & 50\% & 15\% & 29\% & 33\% \\ -3-4 & 31\% & 14\% & 44\% & 41\% & 19\% \\ -4-5 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -5-6 & 16\% & 36\% & 0\% & 0\% & 35\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 99\% & 101\% \\ -Unweighted N & \multicolumn{1}{c}{16} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{11} & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{8} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -0-1 & 6\% & 0\% & 0\% & 43\% \\ -1-2 & 16\% & 0\% & 39\% & 0\% \\ -2-3 & 31\% & 50\% & 0\% & 57\% \\ -3-4 & 31\% & 14\% & 61\% & 0\% \\ -4-5 & 0\% & 0\% & 0\% & 0\% \\ -5-6 & 16\% & 36\% & 0\% & 0\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{16} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{7} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 5. How many dogs do you have?} -\hangindent=0em \parbox{9in}{ -\formatvardescription{5. How many dogs do you have?}} \\ -\addlinespace -\bannera{} - - -0-1 & 12\% & 0\% & 21\% & 23\% & 0\% \\ -1-2 & 15\% & 12\% & 17\% & 9\% & 22\% \\ -2-3 & 17\% & 25\% & 11\% & 9\% & 25\% \\ -3-4 & 24\% & 31\% & 19\% & 0\% & 53\% \\ -4-5 & 32\% & 31\% & 32\% & 58\% & 0\% \\ -\midrule -Totals & 100\% & 99\% & 100\% & 99\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -0-1 & 12\% & 0\% & 33\% & 0\% \\ -1-2 & 15\% & 12\% & 0\% & 46\% \\ -2-3 & 17\% & 25\% & 0\% & 31\% \\ -3-4 & 24\% & 31\% & 17\% & 23\% \\ -4-5 & 32\% & 31\% & 50\% & 0\% \\ -\midrule -Totals & 100\% & 99\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 6. How many dogs do you have?} -\hangindent=0em \parbox{9in}{ -\formatvardescription{6. How many dogs do you have?}} \\ -\addlinespace -\bannera{} - - -0-0.5 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -0.5-1 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -1-1.5 & 12\% & 22\% & 0\% & 0\% & 15\% \\ -1.5-2 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -2-2.5 & 76\% & 56\% & 100\% & 100\% & 71\% \\ -2.5-3 & 12\% & 22\% & 0\% & 0\% & 15\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% & 101\% \\ -Unweighted N & \multicolumn{1}{c}{12} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{7} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -0-0.5 & 0\% & 0\% & 0\% & 0\% \\ -0.5-1 & 0\% & 0\% & 0\% & 0\% \\ -1-1.5 & 12\% & 22\% & 0\% & 0\% \\ -1.5-2 & 0\% & 0\% & 0\% & 0\% \\ -2-2.5 & 76\% & 56\% & 100\% & 100\% \\ -2.5-3 & 12\% & 22\% & 0\% & 0\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{12} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{2} & \multicolumn{1}{c}{6} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 7. Country} -\hangindent=0em \parbox{9in}{ -\formatvardescription{7. Country}} \\ -\addlinespace -\bannera{} - - -Argentina & 0\% & 0\% & 0\% & 0\% & 0\% \\ -Australia & 15\% & 12\% & 17\% & 9\% & 22\% \\ -Austria & 12\% & 12\% & 11\% & 9\% & 15\% \\ -Belgium & 29\% & 12\% & 40\% & 35\% & 22\% \\ -Brazil & 44\% & 62\% & 32\% & 46\% & 42\% \\ -\midrule -Totals & 100\% & 98\% & 100\% & 99\% & 101\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -Argentina & 0\% & 0\% & 0\% & 0\% \\ -Australia & 15\% & 12\% & 0\% & 46\% \\ -Austria & 12\% & 12\% & 17\% & 0\% \\ -Belgium & 29\% & 12\% & 50\% & 23\% \\ -Brazil & 44\% & 62\% & 33\% & 31\% \\ -\midrule -Totals & 100\% & 98\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 8. Age} -\hangindent=0em \parbox{9in}{ -\formatvardescription{8. Age}} \\ -\addlinespace -\bannera{} - - -20-30 & 27\% & 69\% & 0\% & 32\% & 22\% \\ -30-40 & 19\% & 31\% & 11\% & 0\% & 42\% \\ -40-50 & 12\% & 0\% & 21\% & 23\% & 0\% \\ -50-60 & 19\% & 0\% & 32\% & 35\% & 0\% \\ -60-70 & 5\% & 0\% & 8\% & 9\% & 0\% \\ -70-80 & 12\% & 0\% & 19\% & 0\% & 25\% \\ -80-90 & 5\% & 0\% & 8\% & 0\% & 11\% \\ -\midrule -Totals & 99\% & 100\% & 99\% & 99\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -20-30 & 27\% & 69\% & 0\% & 0\% \\ -30-40 & 19\% & 31\% & 17\% & 0\% \\ -40-50 & 12\% & 0\% & 33\% & 0\% \\ -50-60 & 19\% & 0\% & 50\% & 0\% \\ -60-70 & 5\% & 0\% & 0\% & 23\% \\ -70-80 & 12\% & 0\% & 0\% & 54\% \\ -80-90 & 5\% & 0\% & 0\% & 23\% \\ -\midrule -Totals & 99\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 9. Age 2} -\hangindent=0em \parbox{9in}{ -\formatvardescription{9. Age 2}} \\ -\addlinespace -\bannera{} - - -16 to 34 & 40\% & 100\% & 0\% & 32\% & 49\% \\ -35+ & 60\% & 0\% & 100\% & 68\% & 51\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -16 to 34 & 40\% & 100\% & 0\% & 0\% \\ -35+ & 60\% & 0\% & 100\% & 100\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 10. Age 3} -\hangindent=0em \parbox{9in}{ -\formatvardescription{10. Age 3}} \\ -\addlinespace -\bannera{} - - -16 to 34 & 40\% & 100\% & 0\% & 32\% & 49\% \\ -35 to 54 & 38\% & 0\% & 64\% & 58\% & 15\% \\ -55+ & 22\% & 0\% & 36\% & 9\% & 36\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 99\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -16 to 34 & 40\% & 100\% & 0\% & 0\% \\ -35 to 54 & 38\% & 0\% & 100\% & 0\% \\ -55+ & 22\% & 0\% & 0\% & 100\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 11. Age 5} -\hangindent=0em \parbox{9in}{ -\formatvardescription{11. Age 5}} \\ -\addlinespace -\bannera{} - - -16 to 24 & 17\% & 44\% & 0\% & 23\% & 11\% \\ -25 to 34 & 22\% & 56\% & 0\% & 9\% & 38\% \\ -35 to 44 & 19\% & 0\% & 32\% & 23\% & 15\% \\ -45 to 54 & 19\% & 0\% & 32\% & 35\% & 0\% \\ -55+ & 22\% & 0\% & 36\% & 9\% & 36\% \\ -\midrule -Totals & 99\% & 100\% & 100\% & 99\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -16 to 24 & 17\% & 44\% & 0\% & 0\% \\ -25 to 34 & 22\% & 56\% & 0\% & 0\% \\ -35 to 44 & 19\% & 0\% & 50\% & 0\% \\ -45 to 54 & 19\% & 0\% & 50\% & 0\% \\ -55+ & 22\% & 0\% & 0\% & 100\% \\ -\midrule -Totals & 99\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 12. Gender} -\hangindent=0em \parbox{9in}{ -\formatvardescription{12. Gender}} \\ -\addlinespace -\bannera{} - - -Male & 54\% & 44\% & 61\% & 100\% & 0\% \\ -Female & 46\% & 56\% & 39\% & 0\% & 100\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -Male & 54\% & 44\% & 83\% & 23\% \\ -Female & 46\% & 56\% & 17\% & 77\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 13. What is your favorite pet?} -\hangindent=0em \parbox{9in}{ -\formatvardescription{13. What is your favorite pet?}} \\ -\addlinespace -\bannera{} - - -0-0.2 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -0.2-0.4 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -0.4-0.6 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -0.6-0.8 & 30\% & 38\% & 25\% & 18\% & 44\% \\ -0.8-1 & 20\% & 0\% & 33\% & 12\% & 29\% \\ -1-1.2 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -1.2-1.4 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -1.4-1.6 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -1.6-1.8 & 50\% & 62\% & 42\% & 69\% & 27\% \\ -1.8-2 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 99\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -0-0.2 & 0\% & 0\% & 0\% & 0\% \\ -0.2-0.4 & 0\% & 0\% & 0\% & 0\% \\ -0.4-0.6 & 0\% & 0\% & 0\% & 0\% \\ -0.6-0.8 & 30\% & 38\% & 0\% & 69\% \\ -0.8-1 & 20\% & 0\% & 35\% & 31\% \\ -1-1.2 & 0\% & 0\% & 0\% & 0\% \\ -1.2-1.4 & 0\% & 0\% & 0\% & 0\% \\ -1.4-1.6 & 0\% & 0\% & 0\% & 0\% \\ -1.6-1.8 & 50\% & 62\% & 65\% & 0\% \\ -1.8-2 & 0\% & 0\% & 0\% & 0\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 14. Numeric data with values less then 0.} -\hangindent=0em \parbox{9in}{ -\formatvardescription{14. Numeric data with values less then 0.}\\ -\formatvarfiltertext{Not useful.}} \\ -\addlinespace -\bannera{} - - --1--0.5 & 0\% & 0\% & 0\% & 0\% & 0\% \\ --0.5-0 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -0-0.5 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -0.5-1 & 50\% & 38\% & 58\% & 31\% & 73\% \\ -1-1.5 & 0\% & 0\% & 0\% & 0\% & 0\% \\ -1.5-2 & 50\% & 62\% & 42\% & 69\% & 27\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{14} & \multicolumn{1}{c}{10} & \multicolumn{1}{c}{10} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - --1--0.5 & 0\% & 0\% & 0\% & 0\% \\ --0.5-0 & 0\% & 0\% & 0\% & 0\% \\ -0-0.5 & 0\% & 0\% & 0\% & 0\% \\ -0.5-1 & 50\% & 38\% & 35\% & 100\% \\ -1-1.5 & 0\% & 0\% & 0\% & 0\% \\ -1.5-2 & 50\% & 62\% & 65\% & 0\% \\ -\midrule -Totals & 100\% & 100\% & 100\% & 100\% \\ -Unweighted N & \multicolumn{1}{c}{20} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{5} & \multicolumn{1}{c}{9} \\ - -\end{longtable} -\end{center} -\clearpage - - -\begin{center} - -\tbltopa[1.5in] -\addcontentsline{lot}{table}{ 15. Do you have any of these animals as pets? Please select all that apply.} -\hangindent=0em \parbox{9in}{ -\formatvardescription{15. Do you have any of these animals as pets? Please select all that apply.}\\ -\formatvarfiltertext{Uniform base is False.}} \\ -\addlinespace -\bannera{} - - -Cat & 61\% & 0\% & 100\% & 61\% & 0\% \\ -Dog & 78\% & 56\% & 100\% & 100\% & 71\% \\ -Bird & 66\% & 64\% & 70\% & 70\% & 64\% \\ -\midrule -Unweighted N: Min & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{2} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{2} \\ -Unweighted N: Max & \multicolumn{1}{c}{11} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{6} & \multicolumn{1}{c}{7} \\ - -\end{longtable} - - - -\vspace{-.25in} -\tbltopb[1.5in] -\addlinespace -\bannerb{} - - -Cat & 61\% & 0\% & 100\% & 0\% \\ -Dog & 78\% & 56\% & 100\% & 100\% \\ -Bird & 66\% & 64\% & 100\% & 50\% \\ -\midrule -Unweighted N: Min & \multicolumn{1}{c}{8} & \multicolumn{1}{c}{2} & \multicolumn{1}{c}{1} & \multicolumn{1}{c}{4} \\ -Unweighted N: Max & \multicolumn{1}{c}{11} & \multicolumn{1}{c}{4} & \multicolumn{1}{c}{2} & \multicolumn{1}{c}{7} \\ - -\end{longtable} -\end{center} -\clearpage - - -} -\end{document} - diff --git a/tests/testthat/Example-dataset.tex b/tests/testthat/Example-dataset.tex deleted file mode 100644 index 22ebd917..00000000 --- a/tests/testthat/Example-dataset.tex +++ /dev/null @@ -1,343 +0,0 @@ -\documentclass{article} -\usepackage[pdftex]{graphicx} -\usepackage[utf8]{inputenc} -\usepackage{fancyhdr} -\usepackage{sfmath} -\usepackage{comment} -\usepackage[T1]{fontenc} -\usepackage[pdftex=true, pdftoolbar=true, pdfmenubar=true, pdfauthor = {}, pdfcreator = {PDFLaTeX}, pdftitle = {}, colorlinks=true, urlcolor=blue, linkcolor=blue, citecolor=blue, implicit=true, hypertexnames=false]{hyperref} -\usepackage[scaled]{helvet} -\renewcommand*\familydefault{\sfdefault} -\usepackage{booktabs} -\usepackage{tabu} -\usepackage{longtable} -\usepackage{siunitx} -\sisetup{ - round-mode = places, % Rounds numbers - round-precision = 2, % to 2 places - table-format = 3 -} -\usepackage[top=0.6in, bottom=0.6in, left=1in, right=1in, includeheadfoot]{geometry} -\usepackage{array} -\usepackage[english]{babel} -\newcolumntype{B}[2]{>{#1\hspace{0pt}\arraybackslash}b{#2}} -\setlength{\parindent}{0pt} -\usepackage[dvipsnames]{color} -\definecolor{gray}{gray}{0.85} -\pagestyle{fancy} -\renewcommand{\headrulewidth}{0pt} -\renewcommand{\footrulewidth}{0pt} - -\newcolumntype{d}{S} -\newcolumntype{J}{S[table-format=1]} -\newcolumntype{K}{S[table-format=2]} -\newcolumntype{M}{S[table-format=4]} -\newcolumntype{N}{S[table-format=5]} -\newcolumntype{O}{S[table-format=6]} -% default is 3 so it's not included above -\usepackage{float} -\usepackage{marginnote} -\setlength\extrarowheight{2pt} -\newlength\mywidth -\setlength\mywidth{3.5in} -\usepackage{caption} -\captionsetup[table]{labelformat=empty} -\renewcommand*{\marginfont}{\scriptsize\itshape} -\fancyfoot{} -\fancyfoot[R]{\thepage} -\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp} -\let\PBS=\PreserveBackslash -\newcommand{\longtablesep}{\endfirsthead \multicolumn{2}{c}{\textit{}} \\ \endhead \multicolumn{2}{c}{\textit{}} \\ \endfoot \endlastfoot} -\usepackage[titles]{tocloft} -\newcommand{\cftchapfont}{12} -\newcommand{\formatvardescription}[1]{#1} -\newcommand{\formatvarname}[1]{#1} -\newcommand{\formatvaralias}[1]{#1} -\newcommand{\formatvarfiltertext}[1]{\fontsize{8}{12}\textit{#1}} -\newcommand{\formatvarsubname}[1]{#1} -\usepackage{amsmath} -\usepackage{listings} -\usepackage{inconsolata} - -\newenvironment{absolutelynopagebreak} - {\par\nobreak\vfil\penalty0\vfilneg - \vtop\bgroup} - {\par\xdef\tpd{\the\prevdepth}\egroup - \prevdepth=\tpd} - -\fancyhead{} -\fancyhead[L]{{\fontsize{16}{24}\textbf{Example dataset}}} - - -\begin{document} -\setlength{\tabcolsep}{1em} -\setlength{\LTleft}{0pt} -\setlength{\LTright}{\fill} -\setlength{\LTcapwidth}{\textwidth} -\vspace{.25in} - - - - - -\renewcommand{\listtablename}{Table of Contents} - - -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\textbf{All pets owned}\hfill\textbf{\ttfamily{allpets}} - -{\small Multiple Response} - -\vskip 0.10in -Do you have any of these animals as pets? Please select all that apply. -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{allpets}} All pets owned} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{>{}ll} -\toprule -\multicolumn{2}{c}{Rows} \\ -\cmidrule(l{3pt}r{3pt}){1-2} -{Variable} & {Label}\\ -\midrule -\ttfamily{allpets\_1} & Cat\\ - -\ttfamily{allpets\_2} & Dog\\ - -\ttfamily{allpets\_3} & Bird\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\begin{longtable}[l]{Jl} -\toprule -\multicolumn{2}{c}{Columns} \\ -\cmidrule(l{3pt}r{3pt}){1-2} -{Code} & {Label}\\ -\midrule -1 & selected\\ - -2 & not selected\\ - -8 & skipped\\ - -9 & not asked\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\begin{longtable}[l]{lJJJJ} -\toprule -\multicolumn{1}{c}{ } & \multicolumn{4}{c}{Counts} \\ -\cmidrule(l{3pt}r{3pt}){2-5} -{Variable} & {1} & {2} & {8} & {9}\\ -\midrule -\ttfamily{allpets\_1} & 4 & 4 & 4 & 8\\ - -\ttfamily{allpets\_2} & 5 & 3 & 4 & 8\\ - -\ttfamily{allpets\_3} & 5 & 6 & 6 & 3\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Pet}\hfill\textbf{\ttfamily{q1}} - -{\small Categorical} - -\vskip 0.10in -What is your favorite pet? -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{q1}} Pet} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{JlJ} -\toprule -{Code} & {Label} & {Count}\\ -\midrule -1 & Cat & 6\\ -2 & Dog & 4\\ -3 & Bird & 3\\ -8 & Skipped & 3\\ -9 & Not Asked & 4\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Pets by location}\hfill\textbf{\ttfamily{petloc}} - -{\small Grid} - -\vskip 0.10in -Name the kinds of pets you have at these locations. -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{petloc}} Pets by location} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{>{}ll} -\toprule -\multicolumn{2}{c}{Rows} \\ -\cmidrule(l{3pt}r{3pt}){1-2} -{Variable} & {Label}\\ -\midrule -\ttfamily{petloc\_home} & Home\\ - -\ttfamily{petloc\_work} & Work\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\begin{longtable}[l]{Jl} -\toprule -\multicolumn{2}{c}{Columns} \\ -\cmidrule(l{3pt}r{3pt}){1-2} -{Code} & {Label}\\ -\midrule -1 & Cat\\ - -2 & Dog\\ - -3 & Bird\\ - -8 & Skipped\\ - -9 & Not Asked\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\begin{longtable}[l]{lJJJJJ} -\toprule -\multicolumn{1}{c}{ } & \multicolumn{5}{c}{Counts} \\ -\cmidrule(l{3pt}r{3pt}){2-6} -{Variable} & {1} & {2} & {3} & {8} & {9}\\ -\midrule -\ttfamily{petloc\_home} & 5 & 3 & 3 & 4 & 5\\ - -\ttfamily{petloc\_work} & 6 & 4 & 6 & 3 & 1\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Number of dogs}\hfill\textbf{\ttfamily{ndogs}} - -{\small Numeric} - -\vskip 0.10in - -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{ndogs}} Number of dogs} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{cccccc} -\toprule -{Mean} & {SD} & {Min} & {Max} & {n} & {Missing}\\ -\midrule -2 & 1 & 0 & 6 & 16 & 4\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Number of dogs -- With papers}\hfill\textbf{\ttfamily{ndogs\_a}} - -{\small Numeric} - -\vskip 0.10in -How many dogs do you have? -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{ndogs\_a}} Number of dogs -- With papers} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{cccccc} -\toprule -{Mean} & {SD} & {Min} & {Max} & {n} & {Missing}\\ -\midrule -1.95 & 1 & 0 & 5 & 20 & 0\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Number of dogs -- Mutts}\hfill\textbf{\ttfamily{ndogs\_b}} - -{\small Numeric} - -\vskip 0.10in -How many dogs do you have? -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{ndogs\_b}} Number of dogs -- Mutts} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{cccccc} -\toprule -{Mean} & {SD} & {Min} & {Max} & {n} & {Missing}\\ -\midrule -1.58 & 1 & 0 & 3 & 12 & 8\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Pet name}\hfill\textbf{\ttfamily{q3}} - -{\small Text} - -\vskip 0.10in -What is your favorite pet's maiden name? -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{q3}} Pet name} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{ddd} -\toprule -{Filled} & {Missing} & {Max Length}\\ -\midrule -16 & 4 & 8\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Country}\hfill\textbf{\ttfamily{country}} - -{\small Categorical} - -\vskip 0.10in - -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{country}} Country} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{JlJ} -\toprule -{Code} & {Label} & {Count}\\ -\midrule -1 & Argentina & 4\\ -2 & Australia & 4\\ -3 & Austria & 4\\ -4 & Belgium & 4\\ -5 & Brazil & 4\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} -\begin{absolutelynopagebreak} -\begin{absolutelynopagebreak} - -\vskip 0.25in -\textbf{Wave}\hfill\textbf{\ttfamily{wave}} - -{\small Date} - -\vskip 0.10in - -\addcontentsline{lot}{table}{\parbox{1.8in}{\ttfamily{wave}} Wave} -\vskip 0.10in\end{absolutelynopagebreak} -\begin{longtable}[l]{ccc} -\toprule -Filled & Missing & Range\\ -\midrule -20 & 0 & [2014-12-01, 2015-01-01]\\ -\bottomrule -\end{longtable}\end{absolutelynopagebreak} - -\clearpage - - - - -\end{document} diff --git a/tests/testthat/fixtures/example_dataset.rds b/tests/testthat/fixtures/example_dataset.rds new file mode 100644 index 00000000..7a75c7bd Binary files /dev/null and b/tests/testthat/fixtures/example_dataset.rds differ diff --git a/tests/testthat/fixtures/recontact_dataset.rds b/tests/testthat/fixtures/recontact_dataset.rds new file mode 100644 index 00000000..6513e9f4 Binary files /dev/null and b/tests/testthat/fixtures/recontact_dataset.rds differ diff --git a/tests/testthat/fixtures/tabbook_results.rds b/tests/testthat/fixtures/tabbook_results.rds new file mode 100644 index 00000000..18920dda Binary files /dev/null and b/tests/testthat/fixtures/tabbook_results.rds differ diff --git a/tests/testthat/test-codeBookItemBody.R b/tests/testthat/test-codeBookItemBody.R index 32adfbcf..e6df6c26 100644 --- a/tests/testthat/test-codeBookItemBody.R +++ b/tests/testthat/test-codeBookItemBody.R @@ -1,104 +1,147 @@ context("codeBookItemBody") -with_api_fixture("fixtures-1-2-5", { - ds = crunch::loadDataset("Example dataset") - - test_that("codeBookItemBody CategoricalVariable", { - res = codeBookItemBody(ds$q1) - - expect_equal( - attributes(res)$kable_meta$contents, - c("\\{Code\\} & \\{Label\\} & \\{Count\\}", - "1 & Cat & 6", "2 & Dog & 4", "3 & Bird & 3", - "8 & Skipped & 3", "9 & Not Asked & 4") - ) - - expect_equal( - attributes(res)$kable_meta$align_vector_origin, - c("J", "l", "J") - ) - }) - - test_that("codeBookItemBody CategoricalArrayVariable", { - res = codeBookItemBody(ds$petloc) - - expect_equal( - attributes(res$kcounts)$kable_meta$contents, - c("\\{Variable\\} & \\{1\\} & \\{2\\} & \\{3\\} & \\{8\\} & \\{9\\}", - "\\\\ttfamily\\{petloc\\\\_home\\} & 5 & 3 & 3 & 4 & 5", "\\\\ttfamily\\{petloc\\\\_work\\} & 6 & 4 & 6 & 3 & 1" - ) - ) - - expect_equal( - attributes(res$kcounts)$kable_meta$align_vector_origin, - c("l", "J", "J", "J", "J", "J") - ) - }) - - test_that("codeBookItemBody MultipleResponseVariable", { - res = codeBookItemBody(ds$allpets) - - expect_equal( - attributes(res$kcounts)$kable_meta$contents, - c("\\{Variable\\} & \\{1\\} & \\{2\\} & \\{8\\} & \\{9\\}", - "\\\\ttfamily\\{allpets\\\\_1\\} & 4 & 4 & 4 & 8", - "\\\\ttfamily\\{allpets\\\\_2\\} & 5 & 3 & 4 & 8", - "\\\\ttfamily\\{allpets\\\\_3\\} & 5 & 6 & 6 & 3" - ) - ) - expect_equal( - attributes(res$kcounts)$kable_meta$align_vector_origin, - c("l", "J", "J", "J", "J") - ) - }) - - test_that("codeBookItemBody NumericVariable", { - res = codeBookItemBody(ds$ndogs) - - expect_equal( - attributes(res)$kable_meta$contents, - c( - "\\{Mean\\} & \\{SD\\} & \\{Min\\} & \\{Max\\} & \\{n\\} & \\{Missing\\}", - "2 & 1 & 0 & 6 & 16 & 4") - ) +test_that("codeBookItemBody CategoricalVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + smry <- structure(list(id = c("1", "2", "3", "8", "9"), name = c("Cat", + "Dog", "Bird", "Skipped", "Not Asked"), n = c("6", "4", "3", + "3", "4")), class = "data.frame", row.names = c(NA, -5L)) + stub( + codeBookItemBody.CategoricalVariable, + "codeBookSummary.CategoricalVariable", smry + ) + res = codeBookItemBody(ds$q1) + + expect_equal( + attributes(res)$kable_meta$contents, + c("\\{Code\\} & \\{Label\\} & \\{Count\\}", + "1 & Cat & 6", "2 & Dog & 4", "3 & Bird & 3", + "8 & Skipped & 3", "9 & Not Asked & 4") + ) + + expect_equal( + attributes(res)$kable_meta$align_vector_origin, + c("J", "l", "J") + ) +}) - expect_equal( - attributes(res)$kable_meta$align_vector_origin, - rep("c", 6) +test_that("codeBookItemBody CategoricalArrayVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + smry <- structure(list(c("petloc_home", "petloc_work"), c("Home", "Work" + ), `1 Cat` = c(5, 6), `2 Dog` = c(3, 4), `3 Bird` = c(3, 6), + `8 Skipped` = c(4, 3), `9 Not Asked` = c(5, 1)), + row.names = c(NA, -2L), class = "data.frame") + + stub(codeBookItemBody.CategoricalArrayVariable, + "codeBookSummary.CategoricalArrayVariable", smry) + res <- codeBookItemBody(ds$petloc) + expect_equal( + attributes(res$kcounts)$kable_meta$contents, + c("\\{Variable\\} & \\{1\\} & \\{2\\} & \\{3\\} & \\{8\\} & \\{9\\}", + "\\\\ttfamily\\{petloc\\\\_home\\} & 5 & 3 & 3 & 4 & 5", "\\\\ttfamily\\{petloc\\\\_work\\} & 6 & 4 & 6 & 3 & 1" ) - }) + ) + + expect_equal( + attributes(res$kcounts)$kable_meta$align_vector_origin, + c("l", "J", "J", "J", "J", "J") + ) +}) - test_that("codeBookItemBody DatetimeVariable", { - res = codeBookItemBody(ds$wave) - expect_equal( - attributes(res)$kable_meta$contents, - c( - "Filled & Missing & Range", - "20 & 0 & \\[2014-12-01, 2015-01-01\\]" - ) +test_that("codeBookItemBody MultipleResponseVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + smry <- structure(list(c("allpets_1", "allpets_2", "allpets_3"), + c("Cat", "Dog", "Bird"), `1 selected` = c(4, 5, 5), `2 not selected` = c(4, + 3, 6), `8 skipped` = c(4, 4, 6), `9 not asked` = c(8, 8, 3)), row.names = c(NA, + -3L), class = "data.frame") + + stub( + codeBookItemBody.MultipleResponseVariable, + "codeBookSummary.MultipleResponseVariable", + smry, depth = 2) + res = codeBookItemBody(ds$allpets) + expect_equal( + attributes(res$kcounts)$kable_meta$contents, + c("\\{Variable\\} & \\{1\\} & \\{2\\} & \\{8\\} & \\{9\\}", + "\\\\ttfamily\\{allpets\\\\_1\\} & 4 & 4 & 4 & 8", + "\\\\ttfamily\\{allpets\\\\_2\\} & 5 & 3 & 4 & 8", + "\\\\ttfamily\\{allpets\\\\_3\\} & 5 & 6 & 6 & 3" ) + ) + expect_equal( + attributes(res$kcounts)$kable_meta$align_vector_origin, + c("l", "J", "J", "J", "J") + ) +}) - expect_equal( - attributes(res)$kable_meta$align_vector_origin, - c("c", "c", "c") - ) - }) +test_that("codeBookItemBody NumericVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + smry <- structure( + list( + Mean = 2, SD = 1, Min = 0, Max = 6, n = 16, Missing = 4), + class = "data.frame", row.names = c(NA, -1L) + ) + stub(codeBookItemBody.NumericVariable, "codeBookSummary.NumericVariable", smry) + + res = codeBookItemBody(ds$ndogs) + + expect_equal( + attributes(res)$kable_meta$contents, + c( + "\\{Mean\\} & \\{SD\\} & \\{Min\\} & \\{Max\\} & \\{n\\} & \\{Missing\\}", + "2 & 1 & 0 & 6 & 16 & 4") + ) + + expect_equal( + attributes(res)$kable_meta$align_vector_origin, + rep("c", 6) + ) +}) - test_that("codeBookItemBody TextVariable", { - res = codeBookItemBody(ds$q3) - expect_equal( - attributes(res)$kable_meta$contents, - c("\\{Filled\\} & \\{Missing\\} & \\{Max Length\\}", - "16 & 4 & 8" - ) +test_that("codeBookItemBody DatetimeVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + smry = structure(list( + Filled = 20L, Missing = 0L, + Range = "[2014-12-01, 2015-01-01]"), class = "data.frame", + row.names = c(NA, -1L)) + + stub(codeBookItemBody.DatetimeVariable, "codeBookSummary.DatetimeVariable", smry) + res = codeBookItemBody(ds$wave) + + expect_equal( + attributes(res)$kable_meta$contents, + c( + "Filled & Missing & Range", + "20 & 0 & \\[2014-12-01, 2015-01-01\\]" ) + ) + + expect_equal( + attributes(res)$kable_meta$align_vector_origin, + c("c", "c", "c") + ) +}) - expect_equal( - attributes(res)$kable_meta$align_vector_origin, - c("d", "d", "d") +test_that("codeBookItemBody TextVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + smry <- structure( + list( + Filled = 16L, Missing = 4L, `Max Length` = 8L), class = "data.frame", + row.names = c(NA, -1L)) + + stub(codeBookItemBody.TextVariable, "codeBookSummary.TextVariable", smry) + res <- codeBookItemBody(ds$q3) + + expect_equal( + attributes(res)$kable_meta$contents, + c("\\{Filled\\} & \\{Missing\\} & \\{Max Length\\}", + "16 & 4 & 8" ) - }) - + ) + + expect_equal( + attributes(res)$kable_meta$align_vector_origin, + c("d", "d", "d") + ) }) diff --git a/tests/testthat/test-codeBookItemTxtDescription.R b/tests/testthat/test-codeBookItemTxtDescription.R index d8b32ae3..5f17cf06 100644 --- a/tests/testthat/test-codeBookItemTxtDescription.R +++ b/tests/testthat/test-codeBookItemTxtDescription.R @@ -1,62 +1,59 @@ context("codeBookItemTxtDescription") -with_api_fixture("fixtures-1-2-5", { - ds = crunch::loadDataset("Example dataset") +ds <- readRDS(test_path("fixtures/example_dataset.rds")) - test_that("codeBookItemTxtDescription CategoricalVariable", { - res = codeBookItemTxtDescription(ds$q1) +test_that("codeBookItemTxtDescription CategoricalVariable", { + res = codeBookItemTxtDescription(ds$q1) - expect_equal( - res, - "\\vskip 0.10in\nWhat is your favorite pet?\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{q1}} Pet}\n\\vskip 0.10in" - ) - }) - - test_that("codeBookItemTxtDescription CategoricalArrayVariable", { - res = codeBookItemTxtDescription(ds$petloc) + expect_equal( + res, + "\\vskip 0.10in\nWhat is your favorite pet?\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{q1}} Pet}\n\\vskip 0.10in" + ) +}) - expect_equal( - res, - "\\vskip 0.10in\nName the kinds of pets you have at these locations.\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{petloc}} Pets by location}\n\\vskip 0.10in" - ) +test_that("codeBookItemTxtDescription CategoricalArrayVariable", { + res = codeBookItemTxtDescription(ds$petloc) - }) + expect_equal( + res, + "\\vskip 0.10in\nName the kinds of pets you have at these locations.\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{petloc}} Pets by location}\n\\vskip 0.10in" + ) - test_that("codeBookItemTxtDescription MultipleResponseVariable", { - res = codeBookItemTxtDescription(ds$allpets) +}) - expect_equal( - res, - "\\vskip 0.10in\nDo you have any of these animals as pets? Please select all that apply.\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{allpets}} All pets owned}\n\\vskip 0.10in" - ) +test_that("codeBookItemTxtDescription MultipleResponseVariable", { + res = codeBookItemTxtDescription(ds$allpets) - }) + expect_equal( + res, + "\\vskip 0.10in\nDo you have any of these animals as pets? Please select all that apply.\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{allpets}} All pets owned}\n\\vskip 0.10in" + ) - test_that("codeBookItemTxtDescription NumericVariable", { - res = codeBookItemTxtDescription(ds$ndogs) +}) - expect_equal( - res, - "\\vskip 0.10in\n\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{ndogs}} Number of dogs}\n\\vskip 0.10in" - ) +test_that("codeBookItemTxtDescription NumericVariable", { + res = codeBookItemTxtDescription(ds$ndogs) - }) + expect_equal( + res, + "\\vskip 0.10in\n\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{ndogs}} Number of dogs}\n\\vskip 0.10in" + ) - test_that("codeBookItemTxtDescription DatetimeVariable", { - res = codeBookItemTxtDescription(ds$wave) +}) - expect_equal( - res, - "\\vskip 0.10in\n\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{wave}} Wave}\n\\vskip 0.10in" - ) - }) +test_that("codeBookItemTxtDescription DatetimeVariable", { + res = codeBookItemTxtDescription(ds$wave) - test_that("codebookItemTxtDescription notes", { - res = with_mock(codeBookItemTxtDescription(ds$q1), "crunch::notes" = function(x) "This is a note!") - expect_equal( - res, - "\\vskip 0.10in\nWhat is your favorite pet?\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{q1}} Pet}\n\\vskip 0.10in\n\\emph{This is a note!}\n\\vskip 0.10in") + expect_equal( + res, + "\\vskip 0.10in\n\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{wave}} Wave}\n\\vskip 0.10in" + ) +}) - }) +test_that("codebookItemTxtDescription notes", { + res = with_mock(codeBookItemTxtDescription(ds$q1), "crunch::notes" = function(x) "This is a note!") + expect_equal( + res, + "\\vskip 0.10in\nWhat is your favorite pet?\n\\addcontentsline{lot}{table}{\\parbox{1.8in}{\\ttfamily{q1}} Pet}\n\\vskip 0.10in\n\\emph{This is a note!}\n\\vskip 0.10in") -}) +}) \ No newline at end of file diff --git a/tests/testthat/test-codeBookItemTxtHeader.R b/tests/testthat/test-codeBookItemTxtHeader.R index 9e15fb44..f3bb6ba6 100644 --- a/tests/testthat/test-codeBookItemTxtHeader.R +++ b/tests/testthat/test-codeBookItemTxtHeader.R @@ -1,59 +1,52 @@ context("codebookItemTxtHeader") -with_api_fixture("fixtures-1-2-5", { - ds = crunch::loadDataset("Example dataset") +ds <- readRDS(test_path("fixtures/example_dataset.rds")) - test_that("codeBookItemTxtHeader CategoricalVariable", { - res = codeBookItemTxtHeader(ds$q1) +test_that("codeBookItemTxtHeader CategoricalVariable", { + res = codeBookItemTxtHeader(ds$q1) - expect_equal( - res, - "\\textbf{Pet}\\hfill\\textbf{\\ttfamily{q1}}\n\n{\\small Categorical}\n\n" - ) + expect_equal( + res, + "\\textbf{Pet}\\hfill\\textbf{\\ttfamily{q1}}\n\n{\\small Categorical}\n\n" + ) - }) - - test_that("codeBookItemTxtHeader CategoricalArrayVariable", { - res = codeBookItemTxtHeader(ds$petloc) - - expect_equal( - res, - "\\textbf{Pets by location}\\hfill\\textbf{\\ttfamily{petloc}}\n\n{\\small Grid}\n\n" - ) - }) - - test_that("codeBookItemTxtHeader MultipleResponseVariable", { - res = codeBookItemTxtHeader(ds$allpets) - - expect_equal( - res, - "\\textbf{All pets owned}\\hfill\\textbf{\\ttfamily{allpets}}\n\n{\\small Multiple Response}\n\n" - ) +}) - }) +test_that("codeBookItemTxtHeader CategoricalArrayVariable", { + res = codeBookItemTxtHeader(ds$petloc) - test_that("codeBookItemTxtHeader NumericVariable", { - res = codeBookItemTxtHeader(ds$ndogs) + expect_equal( + res, + "\\textbf{Pets by location}\\hfill\\textbf{\\ttfamily{petloc}}\n\n{\\small Grid}\n\n" + ) +}) - expect_equal( - res, - "\\textbf{Number of dogs}\\hfill\\textbf{\\ttfamily{ndogs}}\n\n{\\small Numeric}\n\n" - ) +test_that("codeBookItemTxtHeader MultipleResponseVariable", { + res = codeBookItemTxtHeader(ds$allpets) - }) + expect_equal( + res, + "\\textbf{All pets owned}\\hfill\\textbf{\\ttfamily{allpets}}\n\n{\\small Multiple Response}\n\n" + ) - test_that("codeBookItemTxtHeader DatetimeVariable", { - res = codeBookItemTxtHeader(ds$wave) +}) - expect_equal( - res, - "\\textbf{Wave}\\hfill\\textbf{\\ttfamily{wave}}\n\n{\\small Date}\n\n" - ) +test_that("codeBookItemTxtHeader NumericVariable", { + res = codeBookItemTxtHeader(ds$ndogs) - }) + expect_equal( + res, + "\\textbf{Number of dogs}\\hfill\\textbf{\\ttfamily{ndogs}}\n\n{\\small Numeric}\n\n" + ) +}) - # Test for texEscape() +test_that("codeBookItemTxtHeader DatetimeVariable", { + res = codeBookItemTxtHeader(ds$wave) + expect_equal( + res, + "\\textbf{Wave}\\hfill\\textbf{\\ttfamily{wave}}\n\n{\\small Date}\n\n" + ) }) diff --git a/tests/testthat/test-codeBookSummary.R b/tests/testthat/test-codeBookSummary.R index f4a9be2f..cf460f7b 100644 --- a/tests/testthat/test-codeBookSummary.R +++ b/tests/testthat/test-codeBookSummary.R @@ -1,77 +1,130 @@ context("codeBookSummary") -with_api_fixture("fixtures-1-2-5", { - - ds = loadDataset("Example dataset") - - test_that("codeBookSummary correct for CategoricalVariable", { - r = codeBookSummary(ds$q1) - expect_equal( - r, - structure( - list( - id = c("1", "2", "3", "8", "9"), - name = c("Cat","Dog", "Bird", "Skipped", "Not Asked"), - n = c("6", "4", "3", "3", "4")), - class = "data.frame", row.names = c(NA, -5L) - ) - ) - }) - - test_that("codeBookSummary correct for MultipleResponseVariable", { - r = codeBookSummary(ds$allpets) - - expect_equal( - r, - structure( - list(c("allpets_1", "allpets_2", "allpets_3"), c("Cat", - "Dog", "Bird"), `1 selected` = c(4, 5, 5), - `2 not selected` = c(4, 3, 6), `8 skipped` = c(4, 4, 6), - `9 not asked` = c(8, 8, 3)), row.names = c(NA, -3L), - class = "data.frame") - ) - }) - - test_that("codeBookSummary correct for NumericVariable", { - r = codeBookSummary(ds$ndogs) - - expect_equal( - r, - structure(list( - Mean = 2, SD = 1, Min = 0, Max = 6, - n = 16, Missing = 4), class = "data.frame", - row.names = c(NA, -1L)) - ) - }) - - - test_that("codeBookSummary correct for DatetimeVariable", { - r = codeBookSummary(ds$wave) - - expect_equal( - r, - structure( - list( - Filled = 20L, Missing = 0L, - Range = "[2014-12-01, 2015-01-01]"), - class = "data.frame", row.names = c(NA, -1L)) +test_that("codeBookSummary correct for CategoricalVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + cats <- new("Categories", .Data = list(new("Category", .Data = list(1L, + FALSE, "Cat", 1L), names = c("id", "missing", "name", "numeric_value" + )), new("Category", .Data = list(2L, FALSE, "Dog", 2L), names = c("id", + "missing", "name", "numeric_value")), new("Category", .Data = list( + 3L, FALSE, "Bird", 3L), names = c("id", "missing", "name", + "numeric_value")), new("Category", .Data = list(8L, TRUE, "Skipped", + 8L), names = c("id", "missing", "name", "numeric_value")), + new("Category", .Data = list(9L, TRUE, "Not Asked", 9L), + names = c("id", "missing", "name", "numeric_value")), + new("Category", .Data = list(-1L, TRUE, "No Data", NULL), + names = c("id", "missing", "name", "numeric_value")))) + + tab <- structure(c(Cat = 6, Dog = 4, Bird = 3), .Dim = 3L, .Dimnames = list( + q1 = c("Cat", "Dog", "Bird")), class = "table") + + stub(where = codeBookSummary.CategoricalVariable, what = "crunch::categories", how = function(...) cats) + stub(codeBookSummary.CategoricalVariable, "crunch::table", function(...) tab) + + r = codeBookSummary(ds$q1) + expect_equal( + r, + structure( + list( + id = c("1", "2", "3"), + name = c("Cat","Dog", "Bird"), + n = c("6", "4", "3")), + class = "data.frame", row.names = c(NA, -3L) ) + ) +}) - }) - +test_that("codeBookSummary correct for MultipleResponseVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + + cats <- new("Categories", .Data = list(new("Category", .Data = list(1L, + FALSE, "Cat", 1L), names = c("id", "missing", "name", "numeric_value" + )), new("Category", .Data = list(2L, FALSE, "Dog", 2L), names = c("id", + "missing", "name", "numeric_value")), new("Category", .Data = list( + 3L, FALSE, "Bird", 3L), names = c("id", "missing", "name", + "numeric_value")), new("Category", .Data = list(8L, TRUE, "Skipped", + 8L), names = c("id", "missing", "name", "numeric_value")), + new("Category", .Data = list(9L, TRUE, "Not Asked", 9L), + names = c("id", "missing", "name", "numeric_value")), + new("Category", .Data = list(-1L, TRUE, "No Data", NULL), + names = c("id", "missing", "name", "numeric_value")))) + + fakedf <- data.frame("Cat" = 1, "Dog" = 2, "Bird" = 3) + tab <- structure(list(name = c("selected", "not selected", "skipped", + "not asked"), id = c(1L, 2L, 8L, 9L), missing = c(FALSE, FALSE, + TRUE, TRUE), value = c(1L, 2L, 8L, 9L), drop = c("TRUE", "FALSE", + "8", "9"), n = c(1, 2, 8, 9)), row.names = c(2L, 1L, 4L, 3L), class = "data.frame") + + stub(codeBookSummary.MultipleResponseVariable, "crunch::categories", function(...) cats) + stub(codeBookSummary.MultipleResponseVariable, "crunch::subvariables", function(...) fakedf) + stub(codeBookSummary.MultipleResponseVariable, "codeBookSummary", function(...) tab, depth = 5) + stub(codeBookSummary.MultipleResponseVariable, "names", c("Cat", "Dog", "Bird")) + + r = codeBookSummary.MultipleResponseVariable(ds$allpets) + + # Trade off on simplicity for getting subvar names + # Because names will always return Cat Dog and Bird + expect_equal( + r, + structure( + list(c("Cat", "Dog", "Bird"), c("Cat", + "Dog", "Bird"), `1 selected` = rep(1,3), + `2 not selected` = rep(2,3), `8 skipped` = rep(8,3), + `9 not asked` = rep(9,3)), row.names = c(NA, -3L), + class = "data.frame") + ) +}) - test_that("codeBookSummary correct for TextVariable", { +test_that("codeBookSummary correct for NumericVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + + stub(codeBookSummary.NumericVariable, "as.vector", + c(1, NA, 2, 3, 1, 2, 2, 3, 2, 2, 2, NA, 3, 0, 6, 1, NA, 0, NA, 2)) + + r = codeBookSummary(ds$ndogs) + expect_equal( + r, + structure(list( + Mean = 2, SD = 1, Min = 0, Max = 6, + n = 16, Missing = 4), class = "data.frame", + row.names = c(NA, -1L)) + ) +}) +test_that("codeBookSummary correct for DatetimeVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + + dates <- structure(c( + 16405, 16405, 16405, 16405, 16405, 16405, 16405, + 16405, 16405, 16405, 16436, 16436, 16436, 16436, 16436, 16436, + 16436, 16436, 16436, 16436), class = "Date") + + stub(codeBookSummary.DatetimeVariable, "as.vector", dates) + r = codeBookSummary(ds$wave) + + expect_equal( + r, + structure( + list( + Filled = 20L, Missing = 0L, + Range = "[2014-12-01, 2015-01-01]"), + class = "data.frame", row.names = c(NA, -1L)) + ) +}) +test_that("codeBookSummary correct for TextVariable", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + stub(codeBookSummary.TextVariable, "as.vector", + c("Jasmine", "Clyde", "Geoffrey", "Spike", "Zeus", "Teddy", "Ali", + "Hugo", "Snoopy", "Lady", "Biscuit", NA, "Daisy", "Doug", NA, + "Fluffy", NA, NA, "Felix", "Rocky") + ) r = codeBookSummary(ds$q3) - + expect_equal( r, structure(list(Filled = 16L, Missing = 4L, `Max Length` = 8L), class = "data.frame", row.names = c(NA, -1L)) ) - }) - }) test_that("Fails when passed a garbage object", { diff --git a/tests/testthat/test-prepareExtraSummary.R b/tests/testthat/test-prepareExtraSummary.R index 23b089a8..121bc879 100644 --- a/tests/testthat/test-prepareExtraSummary.R +++ b/tests/testthat/test-prepareExtraSummary.R @@ -1,21 +1,37 @@ context("prepareExtraSummary NumericVariable") -# YANBF: Yet another broken fixture. -with_api_fixture("fixtures-1-2-5", { - - ds <- loadDataset("Example dataset") - - test_that("dataset is not weighted", { - expect_null(weight(ds)) - }) - - test_that("dataset is accessible", { - expect_true(exists("ds")) - }) - +test_that("E-E for NumericVariable, DatetimeVariable and TextVariable summaries", { + ds <- readRDS(test_path("fixtures/example_dataset.rds")) + stub(crosstabs, "crunch::weight", NULL) + typs <- c("multiple_response", "categorical", "categorical_array", "numeric", + "numeric", "numeric", "text", "categorical", "datetime", "numeric") + stub(crosstabs, "crunch::types", typs) + als <- c("allpets", "q1", "petloc", "ndogs", "ndogs_a", "ndogs_b", "q3", + "country", "wave", "caseid") + stub(crosstabs, "crunch::aliases", als) + + bnr <- structure(list(Results = list(`___total___` = structure(list( + alias = "___total___", name = "", type = "Total", old_categories = "Total", + categories_out = "Total", categories = "Total"), class = "BannerVar"), + allpets = structure(list(alias = "allpets", name = "All pets owned", + type = "multiple_response", old_categories = c("Cat", + "Dog", "Bird"), categories_out = c("Cat", "Dog", "Bird" + ), categories = c("Cat", "Dog", "Bird")), class = "BannerVar"))), class = "Banner") + + stub(crosstabs, "banner", bnr) + stub(crosstabs, "tabBooks", readRDS(test_path("fixtures/tabbook_results.rds"))) + stub(crosstabs, "is.weightVariable", FALSE) ct <- crosstabs(ds, include_numeric = TRUE, include_datetime = TRUE, include_verbatims = TRUE) + + +}) + +# YANBF: Yet another broken fixture. +with_api_fixture("fixtures-1-2-5", { + + expect_equal( names(ct$results), diff --git a/tests/testthat/test-recontact_toplines.R b/tests/testthat/test-recontact_toplines.R index 11a982ef..73b3ed93 100644 --- a/tests/testthat/test-recontact_toplines.R +++ b/tests/testthat/test-recontact_toplines.R @@ -28,6 +28,7 @@ test_that("Stops if questions not character", { ), "is.character(questions) is not TRUE", fixed = TRUE) }) + test_that("Stops if suffixes not character", { expect_error( with_mock( diff --git a/tests/testthat/test-writeCodeBook.R b/tests/testthat/test-writeCodeBook.R index ad814559..b28b04f6 100644 --- a/tests/testthat/test-writeCodeBook.R +++ b/tests/testthat/test-writeCodeBook.R @@ -1,13 +1,3 @@ -# with_api_fixture("fixtures-1-2-5", { -# ds = crunch::loadDataset("Example dataset") -# writeCodeBook(ds, pdf = FALSE) -# -# test_that("writeCodeBook creates file as expected", { -# -# -# -# expect_true(file.exists("Example dataset.Rmd")) -# }) -# }) + diff --git a/tests/testthat/test-writeCodeBookLatex.R b/tests/testthat/test-writeCodeBookLatex.R index 3394a9f3..3f8c1e30 100644 --- a/tests/testthat/test-writeCodeBookLatex.R +++ b/tests/testthat/test-writeCodeBookLatex.R @@ -16,7 +16,7 @@ with_api_fixture("fixtures-1-2-5", { ) tex <- readLines("Example-dataset.tex") - original <- readRDS("fixtures/writeCodeBookLatexOne.rds") + original <- readRDS(test_path("fixtures/writeCodeBookLatexOne.rds")) expect_true(length(tex) == length(original)) expect_true(sum(tex %in% original)/length(tex) > 0.98) @@ -123,23 +123,6 @@ with_api_fixture("fixtures-1-2-5", { }) }) -# with_api_fixture("fixtures-1-2-5", { -# ds = loadDataset( -# "https://app.crunch.io/dataset/10c3c3cbd28b420aaa4976b70caba851/" -# ) -# -# test_that("Default tex as expected", { -# suppressWarnings(writeCodeBookLatex( -# ds[1], -# url = "https://app.crunch.io/dataset/10c3c3cbd28b420aaa4976b70caba851/", -# appendix = TRUE, suppress_zero_counts = FALSE, pdf = FALSE) -# ) -# tex <- readLines("Data-for-Progress-National-Issues-Survey----Foreign-Policy.tex") -# original <- readRDS("fixtures/writeCodeBookLatexLongCat.rds") -# expect_true(length(tex) == length(original)) -# expect_true(sum(tex %in% original)/length(tex) > 0.98) -# }) -# }) context("codeBookItemBody")