From fe4a7392ad04d650ed3adda130b2f883f775fdfa Mon Sep 17 00:00:00 2001 From: Doug Manuel Date: Sun, 27 Sep 2026 09:29:20 -0400 Subject: [PATCH 1/3] Stop the legacy generator on formula metadata instead of ignoring it Found in the 0.5.0 release review. When any variable forces the legacy path (an unsupported feature, validate = FALSE, and the other legacy triggers), the legacy generator ignored mockFormula: z = x * 2 came back as unrelated random values (0 of 200 rows matched), or vanished entirely with DerivedVar:: notation, with default validation on. create_mock_data() now stops and names the formula variables, mirroring the survival guard (ADR v05-survival-dates D10). The check runs before the legacy derived-variable exclusion, which would otherwise hide DerivedVar:: rows, and scopes mockFormula to the requested databaseStart the same way the v0.4 adapter does. Both guards share one description of when the legacy path is used. --- R/create_mock_data.R | 43 +++++++++++++++++++++++++--- tests/testthat/test-formula-vars.R | 46 ++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/R/create_mock_data.R b/R/create_mock_data.R index 6d6e0b5..0dd6284 100644 --- a/R/create_mock_data.R +++ b/R/create_mock_data.R @@ -48,6 +48,30 @@ names(spec$variables)[unsupported] } +#' @noRd +.legacy_route_reasons <- function() { + paste0( + "It is used when validate = FALSE, when variable_details is NULL, when ", + "only variable_details has a databaseStart column, or when another ", + "variable uses a feature the v0.4 pipeline does not support. Run with ", + "verbose = TRUE to see which." + ) +} + +#' @noRd +.legacy_formula_variables <- function(enabled_vars, variable_details, databaseStart) { + # Enabled variables with a non-blank mockFormula for the requested + # database, using the same lookup as the v0.4 adapter's carve-out. + if (is.null(variable_details) || !"mockFormula" %in% names(variable_details)) { + return(character(0)) + } + database <- if ("databaseStart" %in% names(variable_details)) databaseStart else NULL + Filter(function(variable) { + details <- .filter_recodeflow_details(variable_details, variable, database) + !.is_blank(suppressWarnings(.details_mock_formula(details))) + }, as.character(enabled_vars$variable)) +} + #' @noRd .has_survival_metadata <- function(variables) { # A row sets anchor, or carries survival parameters (followup_min, @@ -371,6 +395,20 @@ create_mock_data <- function(databaseStart, enabled_vars <- variables } + # Formula variables are computed only by the v0.4 pipeline; the legacy + # dispatcher ignores mockFormula and would return unrelated random values, + # or drop a DerivedVar:: variable, without saying so. Checked before the + # derived exclusion below, which would otherwise hide DerivedVar:: rows. + formula_vars <- .legacy_formula_variables(enabled_vars, variable_details, databaseStart) + if (length(formula_vars) > 0) { + stop( + "Formula variable(s) ", paste(formula_vars, collapse = ", "), + " (mockFormula set) are computed only by the v0.4 pipeline, but the ", + "legacy generator was selected. ", .legacy_route_reasons(), + call. = FALSE + ) + } + # Exclude derived variables (identified by DerivedVar:: and Func:: patterns) if (!is.null(variable_details)) { derived_vars <- identify_derived_vars(enabled_vars, variable_details) @@ -398,10 +436,7 @@ create_mock_data <- function(databaseStart, stop( "Survival date variable(s) ", paste(anchored, collapse = ", "), " (anchor set) are generated only by the v0.4 pipeline, but the ", - "legacy generator was selected. It is used when validate = FALSE, ", - "when variable_details is NULL, when only variable_details has a ", - "databaseStart column, or when another variable uses a feature the ", - "v0.4 pipeline does not support. Run with verbose = TRUE to see which.", + "legacy generator was selected. ", .legacy_route_reasons(), call. = FALSE ) } diff --git a/tests/testthat/test-formula-vars.R b/tests/testthat/test-formula-vars.R index 590c820..eba15f4 100644 --- a/tests/testthat/test-formula-vars.R +++ b/tests/testthat/test-formula-vars.R @@ -457,3 +457,49 @@ test_that("is.na is permitted in mockFormula expressions (survival ADR D8)", { spec, seed = 1) expect_identical(out$flag, rep(0L, 5)) }) + +test_that("the legacy generator stops on formula metadata instead of generating wrong values", { + # Release review of 0.5.0: when any variable forces the legacy path, the + # legacy generator ignored mockFormula, so z = x * 2 came back as unrelated + # random values (or vanished with DerivedVar:: notation), silently. + variables <- data.frame( + variable = c("x", "y", "z"), + variableType = "Continuous", + rType = "double", + role = "enabled", + distribution = c("uniform", "lognormal", NA), + stringsAsFactors = FALSE + ) + details <- data.frame( + variable = c("x", "y", "z"), + recStart = c("[0,1]", "[1,10]", "[0,1]"), + recEnd = "copy", + proportion = 1, + mockFormula = c("", "", "x * 2"), + stringsAsFactors = FALSE + ) + run <- function(v, d, ...) { + suppressWarnings(suppressMessages( + create_mock_data("study", v, d, n = 20, seed = 1, ...) + )) + } + guard <- "Formula variable\\(s\\) z \\(mockFormula set\\) are computed only by the v0.4 pipeline" + + # An unsupported feature on another variable (lognormal y) forces fallback. + expect_error(run(variables, details), guard) + + # With DerivedVar:: notation z used to disappear from the output. + derived <- details + derived$recStart[3] <- "DerivedVar::[x]" + derived$recEnd[3] <- "Func::double_x" + expect_error(run(variables, derived), guard) + + # Explicit validate = FALSE selects the legacy path too. + supported <- variables + supported$distribution[2] <- "uniform" + expect_error(run(supported, details, validate = FALSE), guard) + + # Control: on the v0.4 path the formula is honoured. + result <- run(supported, details) + expect_equal(result$z, result$x * 2) +}) From b803718faacb54471f09fbfea23d92d3407eeda0 Mon Sep 17 00:00:00 2001 From: Doug Manuel Date: Sun, 27 Sep 2026 09:29:20 -0400 Subject: [PATCH 2/3] Fix the minimal example's NaN heights and refresh release docs (#60, #49) height's high-garbage range had an infinite upper bound, (2.1;inf], so sampling produced NaN in the packaged example's default output. The range is now (2.1;2.5] (one cell, changed through read.csv/write.csv), and a contract test pins that the example produces no NaN. Closes #60. README: the minimal-example output showed three columns from the legacy path; it is regenerated by running the code (five representative columns, with a note on the missing codes it shows). The two other README outputs were regenerated too and still match. Closes #49. NEWS: the fixture-corrections entry no longer says survival dates stay off the v0.4 pipeline, and mentions the height range; a Breaking changes entry records the new formula legacy guard. --- NEWS.md | 14 ++++++++++---- README.md | 18 ++++++++++-------- inst/extdata/minimal-example/variables.csv | 2 +- tests/testthat/test-edge-case-contract.R | 11 +++++++++++ 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/NEWS.md b/NEWS.md index ac55c6c..690e2e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -38,6 +38,11 @@ `variable_details = NULL`, detail-level-only `databaseStart`, or another unsupported variable) on metadata that sets `anchor`, `create_mock_data()` stops and names the survival variables rather than dropping them. +- The same applies to formula variables. If the legacy generator is + selected for metadata that sets `mockFormula` on an enabled variable, + `create_mock_data()` stops and names the formula variables. Previously the + legacy generator ignored the formula and returned unrelated random values, + or dropped a `DerivedVar::` variable, without saying so. ## New features @@ -109,10 +114,11 @@ an integer range now fails with a message naming the variable. (#58) - The packaged minimal example corrects two metadata errors: BMI's low garbage range had a stray parenthesis (`[-10;15])`), and height's - low-garbage proportion was 1.00 (every row) instead of 0.01. With these - and #58, every variable in the example except its survival dates now - generates through the v0.4 pipeline. Seeded output for the example - changes. + low-garbage proportion was 1.00 (every row) instead of 0.01; height's + high-garbage range had an infinite upper bound, `(2.1;inf]`, which + produced `NaN` values, and is now `(2.1;2.5]` (#60). With these, #58 and + the survival dates (#40), every variable in the example generates through + the v0.4 pipeline. Seeded output for the example changes. ## Deprecations diff --git a/README.md b/README.md index ba0ea42..0170a9e 100644 --- a/README.md +++ b/README.md @@ -193,16 +193,18 @@ mock_data <- create_mock_data( seed = 123 ) -head(mock_data) -#> age smoking interview_date -#> 1 42 2 2001-08-05 -#> 2 47 2 2002-11-27 -#> 3 73 3 2002-11-14 -#> 4 51 1 2005-01-14 -#> 5 52 1 2001-02-25 -#> 6 76 3 2004-07-25 +head(mock_data[, c("age", "smoking", "BMI", "interview_date", "death_date")]) +#> age smoking BMI interview_date death_date +#> 1 35 3 996.00000 2004-10-20 +#> 2 999 1 31.52719 2004-01-11 +#> 3 72 1 21.02576 2002-01-21 +#> 4 997 2 28.36755 2004-06-25 +#> 5 55 1 29.52888 2001-02-22 +#> 6 998 3 25.80269 2004-01-12 2005-01-11 ``` +The minimal example generates all of its variables; this shows five of them. Values such as 996 and 999 are missing codes declared by the metadata's `NA::` rows. + **What's in those CSV files?** See [inst/extdata/minimal-example/](inst/extdata/minimal-example/README.md) - just variable names, types, ranges, and optional mock-data parameters. **When should you use metadata files?** diff --git a/inst/extdata/minimal-example/variables.csv b/inst/extdata/minimal-example/variables.csv index 0dafc4d..318eac5 100644 --- a/inst/extdata/minimal-example/variables.csv +++ b/inst/extdata/minimal-example/variables.csv @@ -2,7 +2,7 @@ "cchsflow_v0001","age","Age in years","Continuous","integer","enabled,predictor,table1",10,10,,"[;]",,"[;]","normal",50,15,,,,,,"","","","1.0.0","2025-11-09","Normal distribution (mean=50, sd=15)" "cchsflow_v0002","smoking","Smoking status","Categorical","factor","enabled,predictor,table1",20,20,,"",,"","",,,,,,,,"","","","1.0.0","2025-11-09","Categorical variable with proportions" "cchsflow_v0003","BMI","Body mass index","Continuous","double","enabled,outcome,table1",30,30,0.02,"[-10;15]",0.01,"[60;150]","normal",27.5,5.2,,,,,,"","","","1.0.0","2025-11-09","Normal distribution with two-sided contamination" -"cchsflow_v0004","height","Height in meters","Continuous","double","enabled,predictor",40,40,0.01,"[0;1.4)",0.01,"(2.1;inf]","normal",1.7,0.1,,,,,,"","","","1.0.0","2025-11-13","Height for BMI calculation" +"cchsflow_v0004","height","Height in meters","Continuous","double","enabled,predictor",40,40,0.01,"[0;1.4)",0.01,"(2.1;2.5]","normal",1.7,0.1,,,,,,"","","","1.0.0","2025-11-13","Height for BMI calculation" "cchsflow_v0005","weight","Weight in kilograms","Continuous","double","enabled,predictor",50,50,,"[;]",,"[;]","normal",75,15,,,,,,"","","","1.0.0","2025-11-13","Weight for BMI calculation" "cchsflow_v0006","BMI_derived","BMI calculated from height and weight","Continuous","double","enabled,outcome,table1",60,60,,"[;]",,"[;]","",,,,,,,,"","","","1.0.0","2025-11-13","Derived variable: BMI = weight / (height^2)" "ices_v01","interview_date","Interview date (cohort entry)","Continuous","date","enabled,outcome",70,70,0,"[;]",0,"[;]","uniform",,,,,,,,"","","analysis","1.0.0","2025-11-09","Uniform date range (cohort entry)" diff --git a/tests/testthat/test-edge-case-contract.R b/tests/testthat/test-edge-case-contract.R index 555dca4..767fb48 100644 --- a/tests/testthat/test-edge-case-contract.R +++ b/tests/testthat/test-edge-case-contract.R @@ -95,6 +95,17 @@ test_that("create_mock_data generates the minimal example (sanity anchor)", { expect_true(all(names(result) %in% fx$variables$variable)) }) +test_that("the minimal example produces no NaN values (#60)", { + # height's high-garbage range had an infinite upper bound, (2.1;inf], and + # sampling from it produced NaN in the packaged example's default output. + fx <- minimal_example() + result <- suppressWarnings(suppressMessages(create_mock_data( + "minimal-example", fx$variables, fx$variable_details, n = 1000, seed = 1 + ))) + has_nan <- vapply(result, function(x) is.numeric(x) && any(is.nan(x)), logical(1)) + expect_identical(names(result)[has_nan], character(0)) +}) + test_that("create_mock_data accepts n = 0 and returns a full-schema empty frame", { fx <- minimal_example() result <- suppressWarnings(suppressMessages(create_mock_data( From a2d822535a9459742864d01f826085d64cb913b3 Mon Sep 17 00:00:00 2001 From: Doug Manuel Date: Sun, 27 Sep 2026 09:29:20 -0400 Subject: [PATCH 3/3] Commit generated help files so GitHub installs have help pages Found in the 0.5.0 release review. .gitignore excluded man/*.Rd, so the repository held no Rd files: installing from GitHub gave "No man pages found" and no help for any function, including create_mock_data() and mock_spec_survival(). CI hid this because it runs roxygen2 before checking. The 61 generated Rd files are now tracked, as is usual for R packages; regenerate them with devtools::document() when roxygen comments change. --- .gitignore | 3 +- man/MockData-package.Rd | 34 ++++ man/add_garbage.Rd | 127 +++++++++++++ man/apply_garbage.Rd | 84 +++++++++ man/apply_missing_codes.Rd | 47 +++++ man/apply_rtype_defaults.Rd | 80 ++++++++ man/create_cat_var.Rd | 156 ++++++++++++++++ man/create_con_var.Rd | 154 ++++++++++++++++ man/create_date_var.Rd | 160 ++++++++++++++++ man/create_mock_data.Rd | 171 ++++++++++++++++++ man/create_survival_dates.Rd | 206 +++++++++++++++++++++ man/create_wide_survival_data.Rd | 221 +++++++++++++++++++++++ man/determine_proportions.Rd | 36 ++++ man/evaluate_mock_formulas.Rd | 37 ++++ man/extract_distribution_params.Rd | 49 +++++ man/extract_proportions.Rd | 58 ++++++ man/generate_garbage_values.Rd | 39 ++++ man/generate_mock_data_native.Rd | 72 ++++++++ man/generate_mock_data_simstudy.Rd | 71 ++++++++ man/generate_survival_dates.Rd | 57 ++++++ man/get_cycle_variables.Rd | 81 +++++++++ man/get_enabled_variables.Rd | 69 +++++++ man/get_raw_var_dependencies.Rd | 47 +++++ man/get_raw_variables.Rd | 87 +++++++++ man/get_variable_categories.Rd | 34 ++++ man/get_variable_details.Rd | 50 +++++ man/get_variable_details_for_raw.Rd | 47 +++++ man/get_variables_by_role.Rd | 59 ++++++ man/has_garbage.Rd | 40 ++++ man/identify_derived_vars.Rd | 93 ++++++++++ man/import_from_recodeflow.Rd | 122 +++++++++++++ man/is_mock_spec.Rd | 23 +++ man/make_garbage.Rd | 64 +++++++ man/mock_categorical.Rd | 72 ++++++++ man/mock_continuous.Rd | 91 ++++++++++ man/mock_date.Rd | 70 +++++++ man/mock_formula.Rd | 73 ++++++++ man/mock_spec.Rd | 70 +++++++ man/mock_spec_categorical.Rd | 65 +++++++ man/mock_spec_continuous.Rd | 81 +++++++++ man/mock_spec_date.Rd | 63 +++++++ man/mock_spec_formula.Rd | 49 +++++ man/mock_spec_from_recodeflow.Rd | 105 +++++++++++ man/mock_spec_model_hints.Rd | 25 +++ man/mock_spec_survival.Rd | 84 +++++++++ man/parse_range_notation.Rd | 93 ++++++++++ man/parse_variable_start.Rd | 65 +++++++ man/postprocess_mock_data.Rd | 73 ++++++++ man/print.mockdata_validation_result.Rd | 16 ++ man/read_mock_data_config.Rd | 76 ++++++++ man/read_mock_data_config_details.Rd | 78 ++++++++ man/sample_with_proportions.Rd | 47 +++++ man/validate_foreign_keys.Rd | 12 ++ man/validate_garbage.Rd | 12 ++ man/validate_mock_data_config.Rd | 54 ++++++ man/validate_mock_data_config_details.Rd | 84 +++++++++ man/validate_mock_spec.Rd | 31 ++++ man/validate_mockdata_metadata.Rd | 25 +++ man/validate_proportions.Rd | 12 ++ man/validate_rtype.Rd | 12 ++ man/validate_uids.Rd | 12 ++ man/validate_versioning.Rd | 12 ++ 62 files changed, 4238 insertions(+), 2 deletions(-) create mode 100644 man/MockData-package.Rd create mode 100644 man/add_garbage.Rd create mode 100644 man/apply_garbage.Rd create mode 100644 man/apply_missing_codes.Rd create mode 100644 man/apply_rtype_defaults.Rd create mode 100644 man/create_cat_var.Rd create mode 100644 man/create_con_var.Rd create mode 100644 man/create_date_var.Rd create mode 100644 man/create_mock_data.Rd create mode 100644 man/create_survival_dates.Rd create mode 100644 man/create_wide_survival_data.Rd create mode 100644 man/determine_proportions.Rd create mode 100644 man/evaluate_mock_formulas.Rd create mode 100644 man/extract_distribution_params.Rd create mode 100644 man/extract_proportions.Rd create mode 100644 man/generate_garbage_values.Rd create mode 100644 man/generate_mock_data_native.Rd create mode 100644 man/generate_mock_data_simstudy.Rd create mode 100644 man/generate_survival_dates.Rd create mode 100644 man/get_cycle_variables.Rd create mode 100644 man/get_enabled_variables.Rd create mode 100644 man/get_raw_var_dependencies.Rd create mode 100644 man/get_raw_variables.Rd create mode 100644 man/get_variable_categories.Rd create mode 100644 man/get_variable_details.Rd create mode 100644 man/get_variable_details_for_raw.Rd create mode 100644 man/get_variables_by_role.Rd create mode 100644 man/has_garbage.Rd create mode 100644 man/identify_derived_vars.Rd create mode 100644 man/import_from_recodeflow.Rd create mode 100644 man/is_mock_spec.Rd create mode 100644 man/make_garbage.Rd create mode 100644 man/mock_categorical.Rd create mode 100644 man/mock_continuous.Rd create mode 100644 man/mock_date.Rd create mode 100644 man/mock_formula.Rd create mode 100644 man/mock_spec.Rd create mode 100644 man/mock_spec_categorical.Rd create mode 100644 man/mock_spec_continuous.Rd create mode 100644 man/mock_spec_date.Rd create mode 100644 man/mock_spec_formula.Rd create mode 100644 man/mock_spec_from_recodeflow.Rd create mode 100644 man/mock_spec_model_hints.Rd create mode 100644 man/mock_spec_survival.Rd create mode 100644 man/parse_range_notation.Rd create mode 100644 man/parse_variable_start.Rd create mode 100644 man/postprocess_mock_data.Rd create mode 100644 man/print.mockdata_validation_result.Rd create mode 100644 man/read_mock_data_config.Rd create mode 100644 man/read_mock_data_config_details.Rd create mode 100644 man/sample_with_proportions.Rd create mode 100644 man/validate_foreign_keys.Rd create mode 100644 man/validate_garbage.Rd create mode 100644 man/validate_mock_data_config.Rd create mode 100644 man/validate_mock_data_config_details.Rd create mode 100644 man/validate_mock_spec.Rd create mode 100644 man/validate_mockdata_metadata.Rd create mode 100644 man/validate_proportions.Rd create mode 100644 man/validate_rtype.Rd create mode 100644 man/validate_uids.Rd create mode 100644 man/validate_versioning.Rd diff --git a/.gitignore b/.gitignore index 36eedeb..350df57 100644 --- a/.gitignore +++ b/.gitignore @@ -16,8 +16,7 @@ CLAUDE.md # macOS .DS_Store -# Generated documentation -man/*.Rd +# Generated documentation (man/*.Rd is committed so GitHub installs have help pages) docs/ # Quarto/HTML output diff --git a/man/MockData-package.Rd b/man/MockData-package.Rd new file mode 100644 index 0000000..4f19a64 --- /dev/null +++ b/man/MockData-package.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/MockData-package.R +\docType{package} +\name{MockData-package} +\alias{MockData} +\alias{MockData-package} +\title{MockData: Generate Mock Data from Metadata Specifications} +\description{ +Generates mock testing data from small metadata specifications, supplied as in-memory data frames or CSV files. Supports categorical, continuous, date, garbage-data, and survival-style variables for testing data pipelines and documentation examples. Designed for recodeflow-style metadata while also supporting lightweight standalone use. +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://big-life-lab.github.io/MockData/} + \item \url{https://github.com/Big-Life-Lab/MockData} + \item Report bugs at \url{https://github.com/Big-Life-Lab/MockData/issues} +} + +} +\author{ +\strong{Maintainer}: Douglas Manuel \email{dmanuel@ohri.ca} + +Authors: +\itemize{ + \item Juan Li \email{juli@ohri.ca} +} + +Other contributors: +\itemize{ + \item recodeflow contributors [contributor] +} + +} +\keyword{internal} diff --git a/man/add_garbage.Rd b/man/add_garbage.Rd new file mode 100644 index 0000000..9ab877f --- /dev/null +++ b/man/add_garbage.Rd @@ -0,0 +1,127 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_garbage.R +\name{add_garbage} +\alias{add_garbage} +\title{Add garbage specifications to variables data frame} +\usage{ +add_garbage( + variables, + var, + garbage_low_prop = NULL, + garbage_low_range = NULL, + garbage_high_prop = NULL, + garbage_high_range = NULL +) +} +\arguments{ +\item{variables}{Data frame with variable metadata (typically read from +variables.csv)} + +\item{var}{Character. Variable name to add garbage specifications to. Must +exist in \code{variables$variable}.} + +\item{garbage_low_prop}{Numeric. Proportion of observations to generate as +low-range garbage (0-1). If NULL, no low-range garbage is added.} + +\item{garbage_low_range}{Character. Interval notation specifying the range for +low-range garbage values (e.g., \verb{[-2, 0]} for categorical, \verb{[0, 1.4)} for +continuous, \verb{[1900-01-01, 1950-12-31]} for dates). If NULL, no low-range +garbage is added.} + +\item{garbage_high_prop}{Numeric. Proportion of observations to generate as +high-range garbage (0-1). If NULL, no high-range garbage is added.} + +\item{garbage_high_range}{Character. Interval notation specifying the range for +high-range garbage values (e.g., \verb{[10, 15]} for categorical, \verb{[60, 150]} +for continuous, \verb{[2025-01-01, 2099-12-31]} for dates). If NULL, no +high-range garbage is added.} +} +\value{ +Modified variables data frame with garbage specifications added. +If the garbage columns don't exist, they are created and initialized with +NA for all other variables. +} +\description{ +Helper function to add garbage data specifications to a variables data frame. +This provides a convenient way to specify invalid/garbage values for quality +assurance testing. Works consistently across all variable types (categorical, +continuous, date). +} +\details{ +\subsection{Unified garbage API}{ + +All variable types use the same garbage specification pattern: +\itemize{ +\item \code{garbage_low_prop} + \code{garbage_low_range} for values below valid range +\item \code{garbage_high_prop} + \code{garbage_high_range} for values above valid range +} +} + +\subsection{Variable type examples}{ + +\strong{Categorical (ordinal treatment):} + +\if{html}{\out{
}}\preformatted{# Valid codes: 1, 2, 3, 7 +# Generate codes -2, -1, 0 below valid range +vars <- add_garbage(vars, "smoking", + garbage_low_prop = 0.02, garbage_low_range = "[-2, 0]") +}\if{html}{\out{
}} + +\strong{Continuous:} + +\if{html}{\out{
}}\preformatted{# Valid range: [18, 100] +# Generate extreme ages above valid range +vars <- add_garbage(vars, "age", + garbage_high_prop = 0.03, garbage_high_range = "[150, 200]") +}\if{html}{\out{
}} + +\strong{Date:} + +\if{html}{\out{
}}\preformatted{# Valid range: [2000-01-01, 2020-12-31] +# Generate future dates for QA testing +vars <- add_garbage(vars, "death_date", + garbage_high_prop = 0.03, garbage_high_range = "[2025-01-01, 2099-12-31]") +}\if{html}{\out{
}} +} + +\subsection{Pipe-friendly usage}{ + +This function returns the modified variables data frame, making it +pipe-friendly: + +\if{html}{\out{
}}\preformatted{vars_with_garbage <- variables \%>\% + add_garbage("age", garbage_high_prop = 0.03, garbage_high_range = "[150, 200]") \%>\% + add_garbage("smoking", garbage_low_prop = 0.02, garbage_low_range = "[-2, 0]") \%>\% + add_garbage("death_date", garbage_high_prop = 0.03, + garbage_high_range = "[2025-01-01, 2099-12-31]") +}\if{html}{\out{
}} +} +} +\examples{ +variables <- data.frame( + variable = c("age", "smoking"), + variableType = c("Continuous", "Categorical"), + stringsAsFactors = FALSE +) + +# Add high-range garbage to age and low-range garbage to smoking +vars_with_garbage <- variables |> + add_garbage("age", + garbage_high_prop = 0.03, garbage_high_range = "[150, 200]" + ) |> + add_garbage("smoking", + garbage_low_prop = 0.02, garbage_low_range = "[-2, 0]" + ) +vars_with_garbage + +# Pass the result as the `variables` argument of create_mock_data() — +# see ?create_mock_data. +} +\seealso{ +\itemize{ +\item \code{\link[=create_cat_var]{create_cat_var()}} for categorical variable generation +\item \code{\link[=create_con_var]{create_con_var()}} for continuous variable generation +\item \code{\link[=create_date_var]{create_date_var()}} for date variable generation +\item \code{\link[=create_mock_data]{create_mock_data()}} for batch generation of all variables +} +} diff --git a/man/apply_garbage.Rd b/man/apply_garbage.Rd new file mode 100644 index 0000000..11e882f --- /dev/null +++ b/man/apply_garbage.Rd @@ -0,0 +1,84 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{apply_garbage} +\alias{apply_garbage} +\title{Apply garbage data from variables.csv} +\usage{ +apply_garbage( + values, + var_row, + variable_type, + missing_codes = NULL, + seed = NULL +) +} +\arguments{ +\item{values}{Vector. Generated values (already has valid + missing).} + +\item{var_row}{Data frame. Single row from variables.csv (contains garbage data parameters).} + +\item{variable_type}{Character. "categorical", "continuous", "integer", "date".} + +\item{missing_codes}{Numeric vector. Optional. Missing codes extracted from metadata +(rows where recEnd contains "NA::"). Used to exclude missing codes from valid range +calculations. If NULL, uses hardcoded fallback for backward compatibility.} + +\item{seed}{Integer. Optional random seed.} +} +\value{ +Vector with garbage data applied. +} +\description{ +Applies garbage data using parameters from variables.csv extension columns. +Garbage data is specified at the variable level. +} +\details{ +\strong{Garbage data fields (in variables.csv):} + +\strong{Garbage parameters:} +\itemize{ +\item garbage_low_prop: Proportion for low garbage values (0-1) +\item garbage_low_range: Range for low values (interval notation \verb{[min,max]}) +\item garbage_high_prop: Proportion for high garbage values (0-1) +\item garbage_high_range: Range for high values (interval notation \verb{[min,max]}) +} + +\strong{Application order:} +\enumerate{ +\item Apply garbage_low (if specified) +\item Apply garbage_high (if specified) +\item No overlap - indices removed after each application +} + +\strong{Config-driven generation:} +If var_row is NULL or missing garbage fields, no garbage data applied. +} +\examples{ +\dontrun{ +var_row <- data.frame( + variable = "BMI", + garbage_low_prop = 0.02, + garbage_low_range = "[-10,0]", + garbage_high_prop = 0.01, + garbage_high_range = "[60,150]" +) +values <- c(23.5, 45.2, 30.1, 18.9, 25.6) +result <- apply_garbage(values, var_row, "continuous", seed = 123) +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/apply_missing_codes.Rd b/man/apply_missing_codes.Rd new file mode 100644 index 0000000..dcbdc4e --- /dev/null +++ b/man/apply_missing_codes.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{apply_missing_codes} +\alias{apply_missing_codes} +\title{Apply missing codes to values} +\usage{ +apply_missing_codes(values, category_assignments, missing_code_map) +} +\arguments{ +\item{values}{Vector. Generated values (numeric, date, or categorical).} + +\item{category_assignments}{Vector. Category assignments ("valid", "7", "8", "9", etc.).} + +\item{missing_code_map}{Named list. Maps category names to codes (e.g., list("7" = 7, "9" = 9)).} +} +\value{ +Vector with missing codes applied. +} +\description{ +Replaces category assignments with actual missing code values (7, 8, 9, etc.). +Handles different data types (numeric, Date, character). +} +\examples{ +\dontrun{ +values <- c(23.5, 45.2, 18.9, 30.1, 25.6) +assignments <- c("valid", "valid", "7", "valid", "9") +missing_map <- list("7" = 7, "9" = 9) +result <- apply_missing_codes(values, assignments, missing_map) +# Returns: c(23.5, 45.2, 7, 30.1, 9) +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/apply_rtype_defaults.Rd b/man/apply_rtype_defaults.Rd new file mode 100644 index 0000000..5038148 --- /dev/null +++ b/man/apply_rtype_defaults.Rd @@ -0,0 +1,80 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{apply_rtype_defaults} +\alias{apply_rtype_defaults} +\title{Apply rType defaults to variable details} +\usage{ +apply_rtype_defaults(details) +} +\arguments{ +\item{details}{Data frame. Variable details metadata.} +} +\value{ +Data frame with rType column added (if missing) or validated (if present). +} +\description{ +Adds rType column with smart defaults if missing. This enables +language-specific type coercion (R types like integer, double, factor). +} +\details{ +\subsection{Default rType values}{ + +If rType column is missing, defaults are applied based on variable type: +\itemize{ +\item \code{continuous}/\code{cont} → \code{"double"} +\item \code{categorical}/\code{cat} → \code{"factor"} +\item \code{date} → \code{"date"} +\item \code{logical} → \code{"logical"} +\item Unknown → \code{"character"} +} +} + +\subsection{Valid rType values}{ +\itemize{ +\item \code{"integer"}: Whole numbers (age, counts, years) +\item \code{"double"}: Decimal numbers (BMI, income, percentages) +\item \code{"numeric"}: Numeric vector +\item \code{"factor"}: Categorical with levels +\item \code{"character"}: Text codes +\item \code{"logical"}: TRUE/FALSE values +\item \code{"date"}: Date objects +} +} +} +\examples{ +\dontrun{ +# Missing rType - defaults applied +details <- data.frame( + variable = "age", + typeEnd = "cont", + recStart = "[18, 100]" +) +details <- apply_rtype_defaults(details) +# details$rType is now "double" + +# Existing rType - preserved +details <- data.frame( + variable = "age", + typeEnd = "cont", + rType = "integer" +) +details <- apply_rtype_defaults(details) +# details$rType remains "integer" +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/create_cat_var.Rd b/man/create_cat_var.Rd new file mode 100644 index 0000000..7a1bba4 --- /dev/null +++ b/man/create_cat_var.Rd @@ -0,0 +1,156 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_cat_var.R +\name{create_cat_var} +\alias{create_cat_var} +\title{Create categorical variable for MockData} +\usage{ +create_cat_var( + var, + databaseStart, + variables, + variable_details, + df_mock = NULL, + prop_missing = 0, + n, + seed = NULL +) +} +\arguments{ +\item{var}{character. Variable name to generate (column name in output)} + +\item{databaseStart}{character. Database/cycle identifier for filtering metadata +(e.g., "cchs2001_p", "minimal-example"). Used to filter variables and +variable_details to the specified database.} + +\item{variables}{data.frame or character. Variable-level metadata containing: +\itemize{ +\item \code{variable}: Variable names +\item \code{database}: Database identifier (optional, for filtering) +\item \code{rType}: R output type (factor/character/integer/logical) +\item \code{garbage_low_prop}, \code{garbage_high_prop}: Garbage data parameters +} +Can also be a file path (character) to variables.csv.} + +\item{variable_details}{data.frame or character. Detail-level metadata containing: +\itemize{ +\item \code{variable}: Variable name (for joining) +\item \code{recStart}: Category code or range +\item \code{recEnd}: Classification (numeric code, "NA::a", "NA::b") +\item \code{proportion}: Category proportion (0-1, must sum to 1) +\item \code{catLabel}: Category label/description +} +Can also be a file path (character) to variable_details.csv.} + +\item{df_mock}{data.frame. Optional. Existing mock data (to check if variable already exists).} + +\item{prop_missing}{numeric. Proportion of missing values (0-1). Default 0 (no missing). +If > 0, function looks for rows with recEnd containing "NA::" in variable_details.} + +\item{n}{integer. Number of observations to generate.} + +\item{seed}{integer. Optional. Random seed for reproducibility.} +} +\value{ +data.frame with one column (the generated categorical variable), or NULL if: +\itemize{ +\item Variable already exists in df_mock (a message is emitted) +\item No valid categories found in variable_details +} + +Errors if the variable is not found in the variables metadata. Warns and +uses the first row if multiple variables rows match. +} +\description{ +Generates a categorical mock variable based on specifications from metadata. +} +\details{ +\strong{v0.3.0 API}: This function now accepts full metadata data frames and filters +internally for the specified variable and database. This is the "recodeflow pattern" +where filtering is handled inside the function. + +\strong{Generation process}: +\enumerate{ +\item Filter metadata: Extract rows for specified var + database +\item Extract proportions: Read from variable_details (proportion column) +\item Generate population: Sample categories based on proportions +\item Apply missing codes: If prop_missing > 0 or proportions in metadata +\item Apply garbage: Read garbage parameters from variables.csv +\item Apply rType: Coerce to specified R type (factor/character/integer/logical) +} + +\strong{Type coercion (rType)}: +The rType column in variables.csv controls output data type: +\itemize{ +\item \code{"factor"}: Factor with levels from category codes (default for categorical) +\item \code{"character"}: Character vector +\item \code{"integer"}: Integer (for numeric category codes) +\item \code{"logical"}: Logical (for TRUE/FALSE categories) +} + +\strong{Missing data}: +Missing codes are identified by \code{recEnd} containing "NA::": +\itemize{ +\item \code{NA::a}: Skip codes (not applicable) +\item \code{NA::b}: Missing codes (don't know, refusal, not stated) +} +Proportions for missing codes are read from the proportion column in variable_details. + +\strong{Garbage data}: +Garbage parameters are read from variables.csv: +\itemize{ +\item \code{garbage_low_prop}, \code{garbage_low_range}: Below-range invalid values +\item \code{garbage_high_prop}, \code{garbage_high_range}: Above-range invalid values +} +} +\examples{ +variables <- data.frame( + variable = "smoking", + variableType = "Categorical", + rType = "factor", + stringsAsFactors = FALSE +) +variable_details <- data.frame( + variable = "smoking", + recStart = c("1", "2", "3", "7"), + recEnd = c("1", "2", "3", "NA::b"), + proportion = c(0.5, 0.3, 0.17, 0.03), + catLabel = c( + "Never smoker", "Former smoker", "Current smoker", "Don't know" + ), + stringsAsFactors = FALSE +) + +smoking <- create_cat_var( + var = "smoking", + databaseStart = "example", + variables = variables, + variable_details = variable_details, + n = 100, + seed = 123 +) +# Code 7 ("Don't know") is an NA::b missing code, generated at its +# configured proportion alongside the substantive categories. +table(smoking$smoking) + +\dontrun{ +# Not run: requires your own metadata CSV files +# With file paths instead of data frames +result <- create_cat_var( + var = "smoking", + databaseStart = "cchs2001_p", + variables = "path/to/variables.csv", + variable_details = "path/to/variable_details.csv", + n = 1000 +) +} + +} +\seealso{ +Other generators: +\code{\link{create_con_var}()}, +\code{\link{create_date_var}()}, +\code{\link{create_mock_data}()}, +\code{\link{create_survival_dates}()}, +\code{\link{create_wide_survival_data}()} +} +\concept{generators} diff --git a/man/create_con_var.Rd b/man/create_con_var.Rd new file mode 100644 index 0000000..7cc3869 --- /dev/null +++ b/man/create_con_var.Rd @@ -0,0 +1,154 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_con_var.R +\name{create_con_var} +\alias{create_con_var} +\title{Create continuous variable for MockData} +\usage{ +create_con_var( + var, + databaseStart, + variables, + variable_details, + df_mock = NULL, + prop_missing = 0, + n, + seed = NULL +) +} +\arguments{ +\item{var}{character. Variable name to generate (column name in output)} + +\item{databaseStart}{character. Database/cycle identifier for filtering metadata +(e.g., "cchs2001_p", "minimal-example"). Used to filter variables and +variable_details to the specified database.} + +\item{variables}{data.frame or character. Variable-level metadata containing: +\itemize{ +\item \code{variable}: Variable names +\item \code{database}: Database identifier (optional, for filtering) +\item \code{rType}: R output type (integer/double) +\item \code{distribution}: Distribution type (uniform/normal/exponential) +\item \code{mean}, \code{sd}: Normal distribution parameters +\item \code{rate}, \code{shape}: Exponential/Gompertz parameters +\item \code{garbage_low_prop}, \code{garbage_high_prop}: Garbage data parameters +} +Can also be a file path (character) to variables.csv.} + +\item{variable_details}{data.frame or character. Detail-level metadata containing: +\itemize{ +\item \code{variable}: Variable name (for joining) +\item \code{recStart}: Valid range in interval notation (e.g., \verb{[18,100]}) +\item \code{recEnd}: Classification (copy, NA::a, NA::b) +\item \code{proportion}: Category proportion for missing codes +} +Can also be a file path (character) to variable_details.csv.} + +\item{df_mock}{data.frame. Optional. Existing mock data (to check if variable already exists).} + +\item{prop_missing}{numeric. Proportion of missing values (0-1). Default 0 (no missing).} + +\item{n}{integer. Number of observations to generate.} + +\item{seed}{integer. Optional. Random seed for reproducibility.} +} +\value{ +data.frame with one column (the generated continuous variable), or +NULL (with a message) if the variable already exists in df_mock. + +Errors if the variable is not found in the variables metadata. Warns and +uses the first row if multiple variables rows match. +} +\description{ +Generates a continuous mock variable based on specifications from metadata. +} +\details{ +\strong{v0.3.0 API}: This function now accepts full metadata data frames and filters +internally for the specified variable and database. This is the "recodeflow pattern" +where filtering is handled inside the function. + +\strong{Generation process}: +\enumerate{ +\item Filter metadata: Extract rows for specified var + database +\item Extract distribution parameters: Read from variables.csv +\item Extract valid range: Parse from variable_details recStart column +\item Generate population: Based on distribution type (uniform/normal/exponential) +\item Apply missing codes: If proportions specified in metadata +\item Apply garbage: Read garbage parameters from variables.csv +\item Apply rType: Coerce to specified R type (integer/double) +} + +\strong{Type coercion (rType)}: +The rType column in variables.csv controls output data type: +\itemize{ +\item \code{\"integer\"}: Rounds and converts to integer (for age, counts) +\item \code{\"double\"}: Double precision (default for continuous) +} + +\strong{Distribution types}: +\itemize{ +\item \code{\"uniform\"}: Uniform distribution over \verb{[min, max]} from recStart +\item \code{\"normal\"}: Normal distribution (requires mean, sd in variables.csv) +\item \code{\"exponential\"}: Exponential distribution (requires rate in variables.csv) +} + +\strong{Missing data}: +Missing codes are identified by recEnd containing "NA::": +\itemize{ +\item \code{NA::a}: Skip codes (not applicable) +\item \code{NA::b}: Missing codes (don't know, refusal, not stated) +} + +\strong{Garbage data}: +Garbage parameters are read from variables.csv: +\itemize{ +\item \code{garbage_low_prop}, \code{garbage_low_range}: Below-range invalid values +\item \code{garbage_high_prop}, \code{garbage_high_range}: Above-range invalid values +} +} +\examples{ +variables <- data.frame( + variable = "age", + variableType = "Continuous", + rType = "integer", + stringsAsFactors = FALSE +) +variable_details <- data.frame( + variable = "age", + recStart = "[18,85]", + recEnd = "copy", + proportion = 1, + stringsAsFactors = FALSE +) + +age <- create_con_var( + var = "age", + databaseStart = "example", + variables = variables, + variable_details = variable_details, + n = 100, + seed = 123 +) +head(age) + +\dontrun{ +# Not run: requires your own metadata CSV files +# With file paths instead of data frames +result <- create_con_var( + var = "BMI", + databaseStart = "minimal-example", + variables = "path/to/variables.csv", + variable_details = "path/to/variable_details.csv", + n = 1000 +) +} + +} +\seealso{ +Other generators: +\code{\link{create_cat_var}()}, +\code{\link{create_date_var}()}, +\code{\link{create_mock_data}()}, +\code{\link{create_survival_dates}()}, +\code{\link{create_wide_survival_data}()} +} +\concept{generators} diff --git a/man/create_date_var.Rd b/man/create_date_var.Rd new file mode 100644 index 0000000..ebd7e79 --- /dev/null +++ b/man/create_date_var.Rd @@ -0,0 +1,160 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_date_var.R +\name{create_date_var} +\alias{create_date_var} +\title{Create date variable for MockData} +\usage{ +create_date_var( + var, + databaseStart, + variables, + variable_details, + df_mock = NULL, + prop_missing = 0, + n, + seed = NULL +) +} +\arguments{ +\item{var}{character. Variable name to generate (column name in output)} + +\item{databaseStart}{character. Database/cycle identifier for filtering metadata +(e.g., "cchs2001_p", "minimal-example"). Used to filter variables and +variable_details to the specified database.} + +\item{variables}{data.frame or character. Variable-level metadata containing: +\itemize{ +\item \code{variable}: Variable names +\item \code{database}: Database identifier (optional, for filtering) +\item \code{sourceFormat}: Output format ("analysis"/"csv"/"sas") +\item \code{distribution}: Distribution type (uniform/gompertz/exponential) +\item \code{followup_min}, \code{followup_max}: Followup period parameters +\item \code{event_prop}: Proportion experiencing event +\item \code{garbage_high_prop}, \code{garbage_high_range}: Garbage data parameters +} +Can also be a file path (character) to variables.csv.} + +\item{variable_details}{data.frame or character. Detail-level metadata containing: +\itemize{ +\item \code{variable}: Variable name (for joining) +\item \code{recStart}: Date range (e.g., \verb{[01JAN2001,31DEC2020]}) or followup period +\item \code{recEnd}: Classification (copy, NA::a, NA::b) +\item \code{proportion}: Category proportion for missing codes +} +Can also be a file path (character) to variable_details.csv.} + +\item{df_mock}{data.frame. Optional. Existing mock data (to check if variable already exists). +For survival variables, may contain anchor_date column for computing event dates.} + +\item{prop_missing}{numeric. Proportion of missing values (0-1). Default 0 (no missing).} + +\item{n}{integer. Number of observations to generate.} + +\item{seed}{integer. Optional. Random seed for reproducibility.} +} +\value{ +data.frame with one column (the generated date variable), or NULL if: +\itemize{ +\item Variable already exists in df_mock (a message is emitted) +\item No valid date range found in variable_details, or the date +range cannot be parsed +\item Survival-variable preconditions are not met (e.g. df_mock lacks +an anchor_date column, or followup parameters are NA) +} + +Errors if the variable is not found in the variables metadata. Warns and +uses the first row if multiple variables rows match. +} +\description{ +Generates a date mock variable based on specifications from metadata. +} +\details{ +\strong{v0.3.0 API}: This function now accepts full metadata data frames and filters +internally for the specified variable and database. This is the "recodeflow pattern" +where filtering is handled inside the function. + +\strong{Generation process}: +\enumerate{ +\item Filter metadata: Extract rows for specified var + database +\item Extract date parameters: Read from variables.csv and variable_details +\item Generate population: Based on distribution type (uniform/gompertz/exponential) +\item Apply missing codes: If proportions specified in metadata +\item Apply garbage: Read garbage parameters from variables.csv +\item Apply sourceFormat: Convert to specified format (analysis/csv/sas) +} + +\strong{Output format (sourceFormat)}: +The sourceFormat column in variables.csv controls output data type: +\itemize{ +\item \code{"analysis"}: R Date objects (default) +\item \code{"csv"}: Character ISO strings (e.g., "2001-01-15") +\item \code{"sas"}: Numeric days since 1960-01-01 +} + +\strong{Distribution types}: +\itemize{ +\item \code{"uniform"}: Uniform distribution over date range +\item \code{"gompertz"}: Gompertz survival distribution (for time-to-event data) +\item \code{"exponential"}: Exponential distribution (events concentrated near start) +} + +\strong{Survival data generation}: +For variables with followup_min/followup_max/event_prop in variables.csv: +\itemize{ +\item Requires anchor_date column in df_mock (cohort entry/baseline date) +\item Generates event times within followup window +\item event_prop controls proportion experiencing event (vs. censored) +\item Distribution controls event timing (Gompertz typical for survival) +} + +\strong{Missing data}: +Missing codes are identified by recEnd containing "NA::": +\itemize{ +\item \code{NA::a}: Skip codes (not applicable) +\item \code{NA::b}: Missing codes (don't know, refusal, not stated) +} + +\strong{Garbage data}: +Garbage parameters are read from variables.csv: +\itemize{ +\item \code{garbage_high_prop}, \code{garbage_high_range}: Future dates (temporal violations) +} +} +\examples{ +\dontrun{ +# Basic usage with metadata data frames +interview_date <- create_date_var( + var = "interview_date", + databaseStart = "minimal-example", + variables = variables, + variable_details = variable_details, + n = 1000, + seed = 123 +) + +# Expected output: data.frame with 1000 rows, 1 column ("interview_date") +# Values: R Date objects (if sourceFormat="analysis" in metadata) +# Distribution: Based on distribution in metadata (uniform/gompertz) + +# Survival data generation (requires anchor_date in df_mock) +death_date <- create_date_var( + var = "death_date", + databaseStart = "minimal-example", + variables = variables, + variable_details = variable_details, + df_mock = df_mock, # Must contain anchor_date column + n = 1000, + seed = 456 +) +} + +} +\seealso{ +Other generators: +\code{\link{create_cat_var}()}, +\code{\link{create_con_var}()}, +\code{\link{create_mock_data}()}, +\code{\link{create_survival_dates}()}, +\code{\link{create_wide_survival_data}()} +} +\concept{generators} diff --git a/man/create_mock_data.Rd b/man/create_mock_data.Rd new file mode 100644 index 0000000..348cc75 --- /dev/null +++ b/man/create_mock_data.Rd @@ -0,0 +1,171 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_mock_data.R +\name{create_mock_data} +\alias{create_mock_data} +\title{Create mock data from configuration files} +\usage{ +create_mock_data( + databaseStart, + variables, + variable_details = NULL, + n = 1000, + seed = NULL, + validate = TRUE, + verbose = FALSE +) +} +\arguments{ +\item{databaseStart}{Character. The database identifier (e.g., "cchs2001_p", "minimal-example"). +Used to filter variables to those available in the specified database.} + +\item{variables}{data.frame or character. Variable-level metadata containing: +\itemize{ +\item \code{variable}: Variable names +\item \code{variableType}: Variable type (Categorical/Continuous/Date) +\item \code{role}: Role tags (enabled, predictor, outcome, etc.) +\item \code{position}: Display order (optional) +\item \code{database}: Database filter (optional) +} +Can also be a file path (character) to variables.csv.} + +\item{variable_details}{data.frame or character. Detail-level metadata containing: +\itemize{ +\item \code{variable}: Variable name (for joining) +\item \code{recStart}: Category code/range or date interval +\item \code{recEnd}: Classification (numeric code, "NA::a", "NA::b") +\item \code{proportion}: Category proportion (for categorical) +\item \code{catLabel}: Category label/description +} +Can also be a file path (character) to variable_details.csv. +If NULL, uses simple fallback generation.} + +\item{n}{Integer. Number of observations to generate (default 1000). +\code{n = 0} is supported and returns a zero-row data frame with the full +generated schema.} + +\item{seed}{Integer. Optional random seed for reproducibility.} + +\item{validate}{Logical. Whether to use strict generation checks (default +TRUE). When TRUE, unsupported variable types and generator errors stop +generation. When FALSE, those errors are converted to warnings and the +affected variable is skipped.} + +\item{verbose}{Logical. Whether to print progress messages (default FALSE).} +} +\value{ +Data frame with n rows and one column per enabled variable. When the +v0.4 \code{mock_spec} path is used, the result also carries a +\code{mockdata_diagnostics} attribute from \code{\link[=postprocess_mock_data]{postprocess_mock_data()}}. Legacy +fallback paths return plain data frames without that attribute. +} +\description{ +Main orchestrator function that generates complete mock datasets from +configuration files. Reads metadata, filters for enabled variables, +dispatches to type-specific create_* functions, and assembles results +into a complete data frame. +} +\details{ +\strong{v0.4.0 transition}: In strict mode, this function first attempts to use +the v0.4 \code{mock_spec} pipeline: \code{\link[=mock_spec_from_recodeflow]{mock_spec_from_recodeflow()}}, +\code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, and \code{\link[=postprocess_mock_data]{postprocess_mock_data()}}. If the metadata +requests a feature not yet supported by the v0.4 native backend, it falls +back to the v0.3 \verb{create_*} dispatch path so existing users can migrate +gradually. + +The wrapper deliberately stays on the legacy path when \code{validate = FALSE}, +when \code{variable_details = NULL}, when detail-level \code{databaseStart} filtering is +needed but the variables metadata has no \code{databaseStart} column, or when a +variable uses a feature not yet supported by the v0.4 native backend. Set +\code{verbose = TRUE} to see which path was chosen. Survival dates (rows that +set \code{anchor}) are generated only by the v0.4 pipeline: if the legacy path +is selected for metadata that sets \code{anchor}, \code{create_mock_data()} stops and +names the survival variables. + +In the v0.4 path, baseline generation and post-processing draw from distinct, +independent sub-streams derived from a single \code{seed}; output is reproducible +for a given seed and package version but changed in v0.5 (see NEWS). + +\strong{v0.3.0 API}: This function follows the "recodeflow pattern" where it passes +full metadata data frames to create_* functions, which handle internal +filtering. + +\strong{Generation process}: +\enumerate{ +\item Load metadata from file paths or accept data frames +\item Filter for enabled variables (role has an exact "enabled" token) +\item Generate within an isolated RNG sub-stream (if seeded), leaving the caller's RNG state untouched +\item Loop through variables in position order: +- Dispatch to create_cat_var, create_con_var, or create_date_var +- Pass full metadata data frames (functions filter internally) +- Merge result into data frame +\item Return complete dataset +} + +\strong{Fallback mode}: If variable_details = NULL, uses simple default generators +for enabled variables (two-category categorical values, continuous values from +\verb{[0, 100]}, and dates from 2000-01-01 to 2025-12-31). + +\strong{Variable types supported}: +\itemize{ +\item \code{Categorical}: create_cat_var() +\item \code{Continuous}: create_con_var() +\item \code{Date}: create_date_var() +} + +\strong{Configuration schema}: For complete documentation of all configuration columns, +see \code{vignette("reference-config", package = "MockData")}. +} +\examples{ +# The packaged minimal example covers every variable type, including +# survival dates anchored on interview_date. It auto-normalizes some +# proportions, so warnings about that are expected. +mock_data <- create_mock_data( + databaseStart = "minimal-example", + variables = system.file("extdata/minimal-example/variables.csv", + package = "MockData" + ), + variable_details = system.file("extdata/minimal-example/variable_details.csv", + package = "MockData" + ), + n = 100, + seed = 123 +) +str(mock_data) + +# Columns with straightforward metadata generate cleanly: +head(mock_data[, c("age", "smoking", "interview_date")]) + +# Fallback mode: no variable_details, simple default generators. Survival +# dates need the v0.4 pipeline, so drop the rows that set an anchor first. +fallback_variables <- read.csv( + system.file("extdata/minimal-example/variables.csv", package = "MockData"), + stringsAsFactors = FALSE, + check.names = FALSE +) +mock_data <- create_mock_data( + databaseStart = "minimal-example", + variables = fallback_variables[fallback_variables$anchor == "", ], + variable_details = NULL, + n = 500 +) + +} +\seealso{ +\code{\link[=mock_spec_from_recodeflow]{mock_spec_from_recodeflow()}}, \code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, +\code{\link[=postprocess_mock_data]{postprocess_mock_data()}}, \code{\link[=generate_mock_data_simstudy]{generate_mock_data_simstudy()}}, \code{\link[=mock_spec]{mock_spec()}} + +Other generators: +\code{\link{create_cat_var}()}, +\code{\link{create_con_var}()}, +\code{\link{create_date_var}()}, +\code{\link{create_survival_dates}()}, +\code{\link{create_wide_survival_data}()} + +Other mock generation APIs: +\code{\link{generate_mock_data_native}()}, +\code{\link{generate_mock_data_simstudy}()}, +\code{\link{generate_survival_dates}()}, +\code{\link{postprocess_mock_data}()} +} +\concept{generators} +\concept{mock generation APIs} diff --git a/man/create_survival_dates.Rd b/man/create_survival_dates.Rd new file mode 100644 index 0000000..569edce --- /dev/null +++ b/man/create_survival_dates.Rd @@ -0,0 +1,206 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_survival_dates.R +\name{create_survival_dates} +\alias{create_survival_dates} +\title{Create paired survival dates for cohort studies} +\usage{ +create_survival_dates( + entry_var_row = NULL, + entry_details_subset = NULL, + event_var_row = NULL, + event_details_subset = NULL, + n = NULL, + seed = NULL, + df_mock = NULL, + entry_var = NULL, + event_var = NULL, + entry_start = NULL, + entry_end = NULL, + followup_min = NULL, + followup_max = NULL, + length = NULL, + event_distribution = "uniform", + prop_censored = 0, + prop_NA = NULL, + prop_invalid = NULL +) +} +\arguments{ +\item{entry_var_row}{data.frame. Single row from mock_data_config for entry date variable} + +\item{entry_details_subset}{data.frame. Rows from mock_data_config_details for entry date} + +\item{event_var_row}{data.frame. Single row from mock_data_config for event date variable} + +\item{event_details_subset}{data.frame. Rows from mock_data_config_details for event date} + +\item{n}{integer. Number of observations to generate} + +\item{seed}{integer. Random seed for reproducibility. If NULL, uses global seed.} + +\item{df_mock}{data.frame. The current mock data (to check if variables already exist) + +\strong{Configuration v0.1 format (LEGACY):}} + +\item{entry_var}{character. Name for entry date variable} + +\item{event_var}{character. Name for event date variable} + +\item{entry_start}{Date. Start of entry period} + +\item{entry_end}{Date. End of entry period} + +\item{followup_min}{integer. Minimum follow-up days} + +\item{followup_max}{integer. Maximum follow-up days} + +\item{length}{integer. Number of records to generate} + +\item{event_distribution}{character. Distribution for time-to-event: "uniform", "gompertz", "exponential"} + +\item{prop_censored}{numeric. Proportion of records to censor (0-1)} + +\item{prop_NA}{numeric. Proportion of missing values (0-1)} + +\item{prop_invalid}{numeric. Optional. Proportion of temporal violations (entry > event) (0 to 1). If NULL, no invalid dates generated.} +} +\value{ +data.frame with entry_date, event_date, and optionally event_status columns, or NULL if: +\itemize{ +\item Variables already exist in df_mock +\item Missing required configuration +} +} +\description{ +Generates entry and event dates with guaranteed temporal ordering (entry < event). +Useful for survival analysis, cohort studies, and time-to-event modeling. +} +\details{ +\strong{Configuration v0.2 format (NEW):} + +\strong{v0.2 format (NEW):} +\itemize{ +\item Extracts date ranges from entry_details_subset and event_details_subset +\item Generates entry dates uniformly distributed +\item Calculates event dates to ensure entry < event +\item Supports garbage data via \code{catLabel::garbage} in event_details_subset +\item Supports fallback mode: reasonable defaults when details_subset is NULL +} + +\strong{v0.1 format (LEGACY):} +\itemize{ +\item Accepts explicit date ranges and follow-up parameters +\item Supports multiple event distributions (uniform, gompertz, exponential) +\item Handles censoring, missing values, and temporal violations via parameters +} + +The function auto-detects which format based on parameter names. + +This function generates realistic survival data by: +\enumerate{ +\item Creating entry dates uniformly distributed across entry period +\item Generating follow-up times using specified distribution +\item Calculating event dates (entry + follow-up) +\item Optionally censoring events (event_status = 0) +\item Ensuring entry_date < event_date for all records +} + +\strong{Event distributions:} +\itemize{ +\item "uniform": Constant hazard over follow-up period +\item "gompertz": Increasing hazard (mortality increases with time) +\item "exponential": Decreasing hazard (early events more common) +} + +\strong{Censoring:} +When prop_censored > 0, generates event_status column: +\itemize{ +\item 1 = event observed +\item 0 = censored (event_date becomes censoring date) +} +} +\examples{ +\dontrun{ +# v0.2 format - called by create_mock_data() +config <- read_mock_data_config("mock_data_config.csv") +details <- read_mock_data_config_details("mock_data_config_details.csv") +entry_row <- config[config$variable == "study_entry", ] +entry_details <- get_variable_details(details, variable_name = "study_entry") +event_row <- config[config$variable == "death_date", ] +event_details <- get_variable_details(details, variable_name = "death_date") +surv_data <- create_survival_dates( + entry_var_row = entry_row, + entry_details_subset = entry_details, + event_var_row = event_row, + event_details_subset = event_details, + n = 1000, + seed = 123 +) + +# v0.2 with garbage (catLabel::garbage in config_details) +# In mock_data_config_details.csv: +# variable,recEnd,catLabel,proportion +# death_date,followup_min,, +# death_date,followup_max,, +# death_date,garbage,garbage,0.03 +event_details_with_garbage <- get_variable_details(details, variable_name = "death_date") +surv_data_garbage <- create_survival_dates( + entry_var_row = entry_row, + entry_details_subset = entry_details, + event_var_row = event_row, + event_details_subset = event_details_with_garbage, + n = 1000, + seed = 123 +) + +# v0.1 format (legacy) - Basic mortality study +surv_data <- create_survival_dates( + entry_var = "study_entry", + event_var = "death_date", + entry_start = as.Date("2000-01-01"), + entry_end = as.Date("2005-12-31"), + followup_min = 365, + followup_max = 3650, + length = 1000, + df_mock = data.frame(), + event_distribution = "gompertz" +) + +# v0.1 with censoring +surv_data <- create_survival_dates( + entry_var = "cohort_entry", + event_var = "event_date", + entry_start = as.Date("2010-01-01"), + entry_end = as.Date("2015-12-31"), + followup_min = 30, + followup_max = 1825, + length = 500, + df_mock = data.frame(), + event_distribution = "exponential", + prop_censored = 0.3 +) + +# v0.1 with temporal violations for validation testing +surv_data <- create_survival_dates( + entry_var = "interview_date", + event_var = "death_date", + entry_start = as.Date("2015-01-01"), + entry_end = as.Date("2016-12-31"), + followup_min = 30, + followup_max = 3650, + length = 1000, + df_mock = data.frame(), + prop_invalid = 0.03 # 3\% temporal violations +) +} + +} +\seealso{ +Other generators: +\code{\link{create_cat_var}()}, +\code{\link{create_con_var}()}, +\code{\link{create_date_var}()}, +\code{\link{create_mock_data}()}, +\code{\link{create_wide_survival_data}()} +} +\concept{generators} diff --git a/man/create_wide_survival_data.Rd b/man/create_wide_survival_data.Rd new file mode 100644 index 0000000..c7aee17 --- /dev/null +++ b/man/create_wide_survival_data.Rd @@ -0,0 +1,221 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_wide_survival_data.R +\name{create_wide_survival_data} +\alias{create_wide_survival_data} +\title{Create wide survival data for cohort studies} +\usage{ +create_wide_survival_data( + var_entry_date, + var_event_date = NULL, + var_death_date = NULL, + var_ltfu = NULL, + var_admin_censor = NULL, + databaseStart, + variables, + variable_details, + df_mock = NULL, + n, + seed = NULL, + prop_garbage = NULL +) +} +\arguments{ +\item{var_entry_date}{character. Required. Variable name for entry date (baseline).} + +\item{var_event_date}{character. Optional. Variable name for primary event date +(e.g., "dementia_incid_date"). Set to NULL to skip.} + +\item{var_death_date}{character. Optional. Variable name for death date +(competing risk). Set to NULL to skip.} + +\item{var_ltfu}{character. Optional. Variable name for loss-to-follow-up date. +Set to NULL to skip.} + +\item{var_admin_censor}{character. Optional. Variable name for administrative +censoring date. Set to NULL to skip.} + +\item{databaseStart}{character. Required. Database identifier for filtering metadata +(used with databaseStart column in variable_details).} + +\item{variables}{data.frame or character. Full variables metadata (not pre-filtered). +Must contain columns: variable, variableType. +Can also be a file path (character) to variables.csv.} + +\item{variable_details}{data.frame or character. Full variable details metadata +(not pre-filtered). Will be filtered internally using databaseStart column. +Can also be a file path (character) to variable_details.csv.} + +\item{df_mock}{data.frame. Optional. The current mock data to check if variables +already exist and to use as anchor_date source. Default: NULL.} + +\item{n}{integer. Required. Number of observations to generate.} + +\item{seed}{integer. Optional. Random seed for reproducibility. Default: NULL.} + +\item{prop_garbage}{numeric. \strong{DEPRECATED in v0.3.0}. This parameter is no +longer supported. To generate temporal violations for QA testing, use the +\code{garbage_high_prop} and \code{garbage_high_range} parameters in variables.csv +for individual date variables. See Details section for migration guidance. +Default: NULL.} +} +\value{ +data.frame with 1-5 date columns (depending on which variables are +specified), or NULL if variables already exist in df_mock. +} +\description{ +\strong{Deprecated as of MockData 0.5.0.} Add \code{anchor} (and \code{censored_by} for a +competing risk) to the survival dates' rows in \code{variables.csv} and generate +them with \code{\link[=create_mock_data]{create_mock_data()}}; see \code{vignette("tutorial-survival-data")}. +The function still works and warns once per session. +} +\details{ +Generates wide-format survival data (one row per individual) with up to 5 date +variables (entry, event, death, loss-to-follow-up, administrative censoring). +Applies temporal ordering constraints and supports garbage data generation for +QA testing. + +This function implements v0.3.0 "recodeflow pattern" API: +\itemize{ +\item Accepts full metadata data frames (not pre-filtered subsets) +\item Accepts variable names (not variable rows) +\item Filters metadata internally using databaseStart column +} + +\strong{Implementation strategy:} +\enumerate{ +\item Call create_date_var() once for each non-NULL date variable +\item Each variable configured separately in variables.csv with own event_prop, +distribution, followup_min, followup_max, etc. +\item Combine results into single data frame +\item Apply temporal ordering constraints +} + +\strong{Temporal ordering constraints (normal mode):} +\itemize{ +\item Entry date is always baseline (earliest) +\item All other dates must be >= entry_date +\item Death can occur before any event +\item If death < event, set event to NA (censored, not missing) +\item Observation ends at min(event, death, ltfu, admin_censor) +} + +\strong{Temporal violations for QA testing (v0.3.0+):} +This function creates clean, temporally-ordered survival data. To generate +temporal violations for testing data quality pipelines: +\itemize{ +\item Add \code{garbage_high_prop} and \code{garbage_high_range} to individual date variables +in variables.csv (e.g., future death dates beyond 2025) +\item Use \code{\link[=create_date_var]{create_date_var()}} to generate date variables with garbage +\item Test your temporal validation logic separately +\item This approach separates concerns: date-level garbage vs. survival data generation +} + +\strong{Migration from prop_garbage (deprecated in v0.3.0):} + +\if{html}{\out{
}}\preformatted{# OLD (v0.3.0): +surv <- create_wide_survival_data(..., prop_garbage = 0.03) + +# NEW (v0.3.0+): +# Add garbage to date variables in metadata +variables$garbage_high_prop[variables$variable == "death_date"] <- 0.03 +variables$garbage_high_range[variables$variable == "death_date"] <- + "[2025-01-01, 2099-12-31]" +# create_date_var() will apply garbage automatically +surv <- create_wide_survival_data(..., variables = variables) +}\if{html}{\out{
}} + +\strong{Configuration in metadata:} +Each date variable must be defined in variables.csv and variable_details.csv: + +variables.csv: + +\if{html}{\out{
}}\preformatted{variable,variableType,role +interview_date,Date,enabled +dementia_incid_date,Date,enabled +death_date,Date,enabled +}\if{html}{\out{
}} + +variable_details.csv: + +\if{html}{\out{
}}\preformatted{variable,recStart,recEnd,value,proportion +interview_date,[2001-01-01,2005-12-31],copy,NA,NA +dementia_incid_date,[2002-01-01,2021-01-01],followup_min,365,NA +dementia_incid_date,NA,followup_max,7300,NA +dementia_incid_date,NA,event_prop,0.15,NA +death_date,[2002-01-01,2026-01-01],followup_min,365,NA +death_date,NA,followup_max,9125,NA +death_date,NA,event_prop,0.40,NA +}\if{html}{\out{
}} +} +\section{Deprecated arguments}{ + +\code{prop_garbage} is deprecated as of v0.3.0. Configure garbage values on +individual date variables with \code{garbage_high_prop} and \code{garbage_high_range} +instead. +} + +\examples{ +\dontrun{ +# Read metadata +variables <- read.csv("inst/extdata/survival/variables.csv") +variable_details <- read.csv("inst/extdata/survival/variable_details.csv") + +# Generate 5-variable survival data +surv_data <- create_wide_survival_data( + var_entry_date = "interview_date", + var_event_date = "dementia_incid_date", + var_death_date = "death_date", + var_ltfu = "ltfu_date", + var_admin_censor = "admin_censor_date", + databaseStart = "demport", + variables = variables, + variable_details = variable_details, + n = 1000, + seed = 123 +) + +# Generate minimal survival data (entry + event only) +surv_data <- create_wide_survival_data( + var_entry_date = "cohort_entry", + var_event_date = "primary_event_date", + var_death_date = NULL, + var_ltfu = NULL, + var_admin_censor = NULL, + databaseStart = "study", + variables = variables, + variable_details = variable_details, + n = 500, + seed = 456 +) + +# Generate with garbage data for QA testing (v0.3.0+) +# Add garbage to death_date in metadata +vars_with_garbage <- add_garbage(variables, "death_date", + garbage_high_prop = 0.05, + garbage_high_range = "[2025-01-01, 2099-12-31]") + +surv_data <- create_wide_survival_data( + var_entry_date = "interview_date", + var_event_date = "dementia_incid_date", + var_death_date = "death_date", + var_ltfu = NULL, + var_admin_censor = NULL, + databaseStart = "demport", + variables = vars_with_garbage, # Use modified metadata + variable_details = variable_details, + n = 1000, + seed = 789 +) +} + +} +\seealso{ +Other generators: +\code{\link{create_cat_var}()}, +\code{\link{create_con_var}()}, +\code{\link{create_date_var}()}, +\code{\link{create_mock_data}()}, +\code{\link{create_survival_dates}()} +} +\concept{generators} +\keyword{deprecated} diff --git a/man/determine_proportions.Rd b/man/determine_proportions.Rd new file mode 100644 index 0000000..2108648 --- /dev/null +++ b/man/determine_proportions.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/determine_proportions.R +\name{determine_proportions} +\alias{determine_proportions} +\title{Determine proportions for categorical variable generation} +\usage{ +determine_proportions(categories, proportions_param, var_details) +} +\arguments{ +\item{categories}{character vector. Category codes/values} + +\item{proportions_param}{Proportions specification. Can be: +\itemize{ +\item NULL: Use uniform distribution +\item Named list: Maps category codes to proportions +\item Numeric vector: Proportions in same order as categories +}} + +\item{var_details}{data.frame. Variable details metadata (may contain proportion column)} +} +\value{ +Numeric vector of proportions (normalized to sum to 1), same length as categories +} +\description{ +Helper function to determine proportions for categorical variables based on +priority: explicit parameter > metadata column > uniform distribution +} +\details{ +Priority order: +\enumerate{ +\item proportions_param if provided (explicit user specification) +\item proportion column in var_details if present +\item Uniform distribution (fallback) +} +} +\keyword{internal} diff --git a/man/evaluate_mock_formulas.Rd b/man/evaluate_mock_formulas.Rd new file mode 100644 index 0000000..83ee59d --- /dev/null +++ b/man/evaluate_mock_formulas.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec_formula.R +\name{evaluate_mock_formulas} +\alias{evaluate_mock_formulas} +\title{Evaluate formula-derived variables over generated data} +\usage{ +evaluate_mock_formulas(data, spec, seed = NULL) +} +\arguments{ +\item{data}{Data frame of generated baseline values (from +\code{\link[=generate_mock_data_native]{generate_mock_data_native()}} or \code{\link[=generate_mock_data_simstudy]{generate_mock_data_simstudy()}}).} + +\item{spec}{A \code{mock_spec}. Non-formula variables must already be columns of +\code{data}. Strict-validated at entry (like \code{\link[=postprocess_mock_data]{postprocess_mock_data()}}), so an +unparseable formula, an unknown referent, a disallowed symbol, or a +dependency cycle raises here rather than silently skipping the affected +variable.} + +\item{seed}{Optional whole-number seed; reserved for future formulas with +random components. The caller's RNG state and kind are restored on exit.} +} +\value{ +\code{data} with one appended column per formula variable. Returns +\code{data} unchanged if the spec has no formula variables. +} +\description{ +Computes each \code{type = "formula"} variable in \code{spec} by evaluating its +expression over the columns of \code{data}, in dependency order. Evaluation runs +in a restricted environment exposing only the data columns and a fixed +allow-list of base functions — formulas cannot reach the caller's +environment. Any randomness would draw from the isolated \code{formula} +sub-stream (see the v0.5 seed contract), though the Phase A allow-list is +RNG-free, so evaluation is deterministic given \code{data}. +} +\seealso{ +\code{\link[=mock_formula]{mock_formula()}}, \code{\link[=postprocess_mock_data]{postprocess_mock_data()}} +} diff --git a/man/extract_distribution_params.Rd b/man/extract_distribution_params.Rd new file mode 100644 index 0000000..6c7e9d3 --- /dev/null +++ b/man/extract_distribution_params.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{extract_distribution_params} +\alias{extract_distribution_params} +\title{Extract distribution parameters from details} +\usage{ +extract_distribution_params(details_subset, distribution_type = NULL) +} +\arguments{ +\item{details_subset}{Data frame. Rows from details for one variable.} + +\item{distribution_type}{Character. Optional ("normal", "uniform", "gompertz", +"exponential", "poisson"). If NULL, attempts auto-detection.} +} +\value{ +Named list with distribution type and parameters: +\itemize{ +\item distribution: Character. Distribution type. +\item mean, sd: Numeric. For normal distribution. +\item rate, shape: Numeric. For Gompertz/exponential. +\item range_min, range_max: Numeric. For uniform or truncation. +} +} +\description{ +Extracts distribution-specific parameters (mean, sd, rate, shape, range) from +details subset. Auto-detects distribution type if not specified. +} +\examples{ +\dontrun{ +params <- extract_distribution_params(details_subset, "normal") +# Returns: list(distribution = "normal", mean = 25, sd = 5, range_min = 18.5, range_max = 40) +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/extract_proportions.Rd b/man/extract_proportions.Rd new file mode 100644 index 0000000..be46857 --- /dev/null +++ b/man/extract_proportions.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{extract_proportions} +\alias{extract_proportions} +\title{Extract proportions from details subset} +\usage{ +extract_proportions(details_subset, variable_name = "variable") +} +\arguments{ +\item{details_subset}{Data frame. Rows from details for one variable.} + +\item{variable_name}{Character. Variable name for error messages.} +} +\value{ +Named list with: +\itemize{ +\item valid: Numeric. Proportion for valid values (sum of all non-missing, non-garbage) +\item missing: Named list. Proportion for each missing code (e.g., "7" = 0.03) +\item garbage: Named list. Proportion for each garbage type (e.g., garbage_low = 0.02) +\item categories: Character vector. All non-garbage recStart values +\item category_proportions: Numeric vector. Proportions for sampling (aligned with categories) +} +} +\description{ +Parses proportion column and organizes by type (valid, missing, garbage). +Validates that valid + missing proportions sum to 1.0 (±0.001 tolerance). +Auto-normalizes with warning if sum != 1.0. +} +\details{ +Population proportions (valid + missing) must sum to 1.0. Garbage proportions +are separate and applied to valid values only. + +If proportions are NA or missing, returns uniform probabilities. +} +\examples{ +\dontrun{ +details <- read_mock_data_config_details("details.csv") +details_subset <- details[details$variable == "ADL_01", ] +props <- extract_proportions(details_subset, "ADL_01") +# Returns: list(valid = 0.92, missing = list("7" = 0.03, "9" = 0.05), ...) +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/generate_garbage_values.Rd b/man/generate_garbage_values.Rd new file mode 100644 index 0000000..26096ae --- /dev/null +++ b/man/generate_garbage_values.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{generate_garbage_values} +\alias{generate_garbage_values} +\title{Generate garbage values} +\usage{ +generate_garbage_values(garbage_type, garbage_row, variable_type, n) +} +\arguments{ +\item{garbage_type}{Character. "garbage_low", "garbage_high", "garbage_future", etc.} + +\item{garbage_row}{Data frame row. Contains recStart with interval notation for garbage range.} + +\item{variable_type}{Character. "continuous", "date", etc.} + +\item{n}{Integer. Number of values to generate.} +} +\value{ +Vector of garbage values. +} +\description{ +Generates implausible values for garbage based on type. +Helper function for make_garbage(). +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/generate_mock_data_native.Rd b/man/generate_mock_data_native.Rd new file mode 100644 index 0000000..3048f12 --- /dev/null +++ b/man/generate_mock_data_native.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec_native.R +\name{generate_mock_data_native} +\alias{generate_mock_data_native} +\title{Generate mock data with the native backend} +\usage{ +generate_mock_data_native(spec, n, seed = NULL) +} +\arguments{ +\item{spec}{A \code{mock_spec} object.} + +\item{n}{Non-negative whole number of rows to generate.} + +\item{seed}{Optional whole-number seed. Generation uses an isolated +L'Ecuyer-CMRG sub-stream and restores the caller's RNG state and kind on +exit, so output is reproducible for a given seed and package version +without perturbing the caller's RNG.} +} +\value{ +A data frame with \code{n} rows and one column per non-derived +\code{mock_spec} variable (\code{type = "survival"} and \code{type = "formula"} +variables are appended afterwards by \code{\link[=generate_survival_dates]{generate_survival_dates()}} and +\code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}). +} +\description{ +\code{generate_mock_data_native()} consumes a validated \code{mock_spec} and generates +baseline valid values using MockData's native R backend. This milestone does +not yet apply missing-code injection, garbage values, diagnostics, or +optional \code{simstudy} features. +} +\details{ +The native backend is the default MIT-licensed baseline engine. It currently +supports uniform continuous variables, truncated-normal continuous variables, +truncated-exponential continuous variables, categorical variables, and +uniform calendar dates. Missing codes, garbage +values, and diagnostics are intentionally handled by \code{\link[=postprocess_mock_data]{postprocess_mock_data()}} +so that all backends share the same audit trail. + +\code{type = "formula"} variables are skipped by this backend — they carry no +distribution to sample from. They are computed post-baseline by +\code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}, which evaluates each formula over this +function's output columns in dependency order. A spec containing only +formula variables still returns an \code{n}-row, zero-column data frame here (see +\code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}} for how columns are appended afterwards). A +stray \code{formula} field on a variable of some other type remains an +unsupported/fallback trigger. +} +\examples{ +spec <- mock_spec( + mock_spec_continuous("age", range = c(18, 85), rtype = "integer"), + mock_spec_categorical( + "smoking", + levels = c("never", "former", "current"), + proportions = c(0.5, 0.3, 0.2) + ) +) +data <- generate_mock_data_native(spec, n = 10, seed = 1) +head(data) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_continuous]{mock_continuous()}}, \code{\link[=mock_spec_from_recodeflow]{mock_spec_from_recodeflow()}}, +\code{\link[=postprocess_mock_data]{postprocess_mock_data()}}, \code{\link[=generate_mock_data_simstudy]{generate_mock_data_simstudy()}}, +\code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}} + +Other mock generation APIs: +\code{\link{create_mock_data}()}, +\code{\link{generate_mock_data_simstudy}()}, +\code{\link{generate_survival_dates}()}, +\code{\link{postprocess_mock_data}()} +} +\concept{mock generation APIs} diff --git a/man/generate_mock_data_simstudy.Rd b/man/generate_mock_data_simstudy.Rd new file mode 100644 index 0000000..1b2ef4c --- /dev/null +++ b/man/generate_mock_data_simstudy.Rd @@ -0,0 +1,71 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec_simstudy.R +\name{generate_mock_data_simstudy} +\alias{generate_mock_data_simstudy} +\title{Generate mock data with the optional simstudy backend} +\usage{ +generate_mock_data_simstudy(spec, n, seed = NULL) +} +\arguments{ +\item{spec}{A \code{mock_spec} object.} + +\item{n}{Non-negative whole number of rows to generate.} + +\item{seed}{Optional whole-number seed. Generation uses an isolated +L'Ecuyer-CMRG sub-stream and restores the caller's RNG state and kind on +exit, so output is reproducible for a given seed and package version +without perturbing the caller's RNG.} +} +\value{ +A data frame with \code{n} rows and one column per non-formula +\code{mock_spec} variable (\code{type = "formula"} variables are appended +afterwards by \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}). +} +\description{ +\code{generate_mock_data_simstudy()} consumes a validated \code{mock_spec} and +generates baseline valid values through the optional \code{simstudy} package for +supported uniform continuous and categorical variables. MockData remains +responsible for missing-code injection, garbage values, and diagnostics +through \code{\link[=postprocess_mock_data]{postprocess_mock_data()}}. +} +\details{ +Variables that need MockData semantics not covered by this milestone, such as +truncated normal ranges and calendar dates, are generated by MockData's native +path inside the same seeded call. + +\code{simstudy} is an optional \code{Suggests} dependency and is GPL-3 licensed; +MockData remains MIT licensed by keeping this backend soft-gated and by +retaining \code{\link[=generate_mock_data_native]{generate_mock_data_native()}} as the default engine. Use this +backend when \code{simstudy} is installed and you want to exercise the optional +engine path. It currently delegates only categorical and uniform continuous +baseline generation to \code{simstudy}; unsupported variables are routed through +MockData's native backend so that a single specification can mix capabilities. + +Missing-code assignment, garbage values, and diagnostics are not delegated to +\code{simstudy}. They remain MockData-owned post-processing so both backends share +the same auditability contract. + +Like \code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, this backend skips \code{type = "formula"} +variables — they carry no distribution to sample from. They are computed +post-baseline by \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}, which works over either +backend's output. +} +\examples{ +spec <- mock_continuous("age", range = c(18, 85), rtype = "integer") +if (requireNamespace("simstudy", quietly = TRUE)) { + data <- generate_mock_data_simstudy(spec, n = 10, seed = 1) + head(data) +} + +} +\seealso{ +\code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, \code{\link[=postprocess_mock_data]{postprocess_mock_data()}}, +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}} + +Other mock generation APIs: +\code{\link{create_mock_data}()}, +\code{\link{generate_mock_data_native}()}, +\code{\link{generate_survival_dates}()}, +\code{\link{postprocess_mock_data}()} +} +\concept{mock generation APIs} diff --git a/man/generate_survival_dates.Rd b/man/generate_survival_dates.Rd new file mode 100644 index 0000000..10d08d2 --- /dev/null +++ b/man/generate_survival_dates.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec_survival.R +\name{generate_survival_dates} +\alias{generate_survival_dates} +\title{Generate survival dates from their anchor dates} +\usage{ +generate_survival_dates(data, spec, seed = NULL) +} +\arguments{ +\item{data}{Data frame of generated baseline values (from +\code{\link[=generate_mock_data_native]{generate_mock_data_native()}} or \code{\link[=generate_mock_data_simstudy]{generate_mock_data_simstudy()}}), +containing each anchor column as class \code{Date}.} + +\item{spec}{A \code{mock_spec}. Strict-validated at entry.} + +\item{seed}{Optional whole-number seed. The caller's RNG state and kind are +restored on exit.} +} +\value{ +\code{data} with one appended \code{Date} column per survival variable. +Returns \code{data} unchanged if the spec has no survival variables. +} +\description{ +Computes each \code{type = "survival"} variable in \code{spec} from its anchor column +in \code{data}: \code{floor(n * event_prop)} rows receive a date a follow-up time +after the anchor (whole days, within \verb{[followup_min, followup_max]}), and +the rest are \code{NA}. Variables are processed in dependency order; each is +drawn and then has its rules applied: a date earlier than its anchor +becomes \code{NA}, and, if \code{censored_by} is set, a date later than the censoring +date becomes \code{NA}. Draws use the isolated \code{survival} sub-stream of the seed +contract. +} +\details{ +Survival dates describe true values. \code{\link[=postprocess_mock_data]{postprocess_mock_data()}} applies +missing codes and garbage afterwards, independently for each column. +} +\examples{ +spec <- mock_spec( + mock_spec_date("entry", range = as.Date(c("2001-01-01", "2005-12-31"))), + mock_spec_survival("death", anchor = "entry", + followup_min = 365, followup_max = 7300, event_prop = 0.2) +) +baseline <- generate_mock_data_native(spec, n = 10, seed = 1) +generate_survival_dates(baseline, spec, seed = 1) + +} +\seealso{ +\code{\link[=mock_spec_survival]{mock_spec_survival()}}, \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}, +\code{\link[=postprocess_mock_data]{postprocess_mock_data()}} + +Other mock generation APIs: +\code{\link{create_mock_data}()}, +\code{\link{generate_mock_data_native}()}, +\code{\link{generate_mock_data_simstudy}()}, +\code{\link{postprocess_mock_data}()} +} +\concept{mock generation APIs} diff --git a/man/get_cycle_variables.Rd b/man/get_cycle_variables.Rd new file mode 100644 index 0000000..83693a8 --- /dev/null +++ b/man/get_cycle_variables.Rd @@ -0,0 +1,81 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{get_cycle_variables} +\alias{get_cycle_variables} +\title{Get list of variables used in a specific database/cycle} +\usage{ +get_cycle_variables(cycle, variables, variable_details, include_derived = TRUE) +} +\arguments{ +\item{cycle}{Character string specifying the database/cycle (e.g., "cycle1", +"cycle1_meds" for CHMS; "cchs2001", "cchs2017_p" for CCHS).} + +\item{variables}{Data frame from variables.csv containing variable metadata.} + +\item{variable_details}{Data frame from variable_details.csv containing detailed recoding specifications.} + +\item{include_derived}{Logical. Should derived variables be included? Default is TRUE.} +} +\value{ +Data frame with columns: +\itemize{ +\item variable - Harmonized variable name +\item variable_raw - Raw source variable name (extracted from variableStart) +\item label - Human-readable label +\item variableType - "Categorical" or "Continuous" +\item databaseStart - Which databases/cycles the variable appears in +\item variableStart - Original variableStart string (for reference) +} + +Returns empty data frame if no variables found for the database/cycle. +} +\description{ +Returns a data frame containing all variables that are available in a +specified database/cycle, with their metadata and extracted raw variable names. +} +\details{ +The function filters variables.csv by checking if the database/cycle appears +in the \code{databaseStart} field (exact match), then uses \code{\link{parse_variable_start}} +to extract the raw variable name from the \code{variableStart} field. + +\strong{Important}: Uses exact matching to avoid false positives (e.g., "cycle1" +should not match "cycle1_meds"). + +Derived variables (those with "DerivedVar::" in variableStart) return NA for +variable_raw since they require custom derivation logic. +} +\examples{ +\dontrun{ +# Load metadata +variables <- read.csv("inst/extdata/variables.csv") +variable_details <- read.csv("inst/extdata/variable-details.csv") + +# CHMS example +cycle1_vars <- get_cycle_variables("cycle1", variables, variable_details) + +# CCHS example +cchs2001_vars <- get_cycle_variables("cchs2001", variables, variable_details) + +# Exclude derived variables +cycle1_original <- get_cycle_variables("cycle1", variables, variable_details, + include_derived = FALSE) +} + +} +\seealso{ +\code{\link{parse_variable_start}} + +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/get_enabled_variables.Rd b/man/get_enabled_variables.Rd new file mode 100644 index 0000000..b840289 --- /dev/null +++ b/man/get_enabled_variables.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config_helpers.R +\name{get_enabled_variables} +\alias{get_enabled_variables} +\title{Get enabled variables} +\usage{ +get_enabled_variables(config, exclude_derived = TRUE, variable_details = NULL) +} +\arguments{ +\item{config}{Data frame. Configuration from read_mock_data_config().} + +\item{exclude_derived}{Logical. If TRUE (default), exclude derived variables +identified by recodeflow patterns (DerivedVar::, Func::). Derived variables +are calculated from raw variables and should not be generated as mock data.} + +\item{variable_details}{Data frame. Required when exclude_derived = TRUE. +Detail-level metadata with columns: variable, recStart, recEnd. Contains +DerivedVar:: and Func:: patterns that identify derived variables.} +} +\value{ +Data frame with subset of config rows where role contains "enabled" +and not identified as derived (unless exclude_derived = FALSE). +} +\description{ +Convenience function to get all variables marked with role "enabled", +excluding derived variables by default. Derived variables should be +calculated after generating raw mock data, not generated directly. +} +\details{ +The "enabled" role indicates variables that should be included when generating +mock data. However, derived variables are calculated from other variables and +should NOT be generated directly. + +\strong{Derived variables}: Variables calculated from raw data (e.g., BMI from +height and weight, pack-years from smoking variables). These are identified +by recodeflow patterns in variable_details: +\itemize{ +\item \verb{DerivedVar::[VAR1, VAR2, ...]} in variable_details.recStart +\item \code{Func::function_name} in variable_details.recEnd +} + +\strong{Default behavior}: Excludes derived variables to prevent generating +variables that should be calculated from raw data. + +\strong{Note}: This function uses pattern-based detection (recodeflow approach), +NOT role column flags. The role column is NOT checked for "derived" status. +} +\examples{ +\dontrun{ +# Load configuration +config <- read_mock_data_config("inst/extdata/mock_data_config.csv") +variable_details <- read.csv("inst/extdata/variable_details.csv") + +# Get only enabled RAW variables (excludes derived, default) +enabled_vars <- get_enabled_variables(config, variable_details = variable_details) + +# Include derived variables (not recommended) +all_enabled <- get_enabled_variables(config, exclude_derived = FALSE) + +# View enabled variable names +enabled_vars$variable +} + +} +\seealso{ +Other configuration: +\code{\link{get_variables_by_role}()} +} +\concept{configuration} diff --git a/man/get_raw_var_dependencies.Rd b/man/get_raw_var_dependencies.Rd new file mode 100644 index 0000000..3c26019 --- /dev/null +++ b/man/get_raw_var_dependencies.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/identify_derived_vars.R +\name{get_raw_var_dependencies} +\alias{get_raw_var_dependencies} +\title{Extract raw variable dependencies from derived variable metadata} +\usage{ +get_raw_var_dependencies(derived_var, variable_details) +} +\arguments{ +\item{derived_var}{character. Name of the derived variable} + +\item{variable_details}{data.frame. Detail-level metadata with columns: +variable, recStart} +} +\value{ +Character vector of raw variable names that the derived variable +depends on. Returns character(0) if no dependencies found. +} +\description{ +For a given derived variable, extract the list of raw variables it depends on +by parsing the DerivedVar::\link{...} pattern in variable_details. +} +\details{ +Parses patterns like: +\itemize{ +\item \verb{DerivedVar::[HWTGHTM, HWTGWTK]} → c("HWTGHTM", "HWTGWTK") +\item \verb{DerivedVar::[ADL_01, ADL_02, ADL_03, ADL_04, ADL_05]} → c("ADL_01", ...) +} +} +\examples{ +\dontrun{ +variable_details <- data.frame( + variable = c("HWTGBMI_der"), + recStart = c("DerivedVar::[HWTGHTM, HWTGWTK]"), + stringsAsFactors = FALSE +) + +get_raw_var_dependencies("HWTGBMI_der", variable_details) +# Returns: c("HWTGHTM", "HWTGWTK") +} + +} +\seealso{ +Other helpers: +\code{\link{identify_derived_vars}()} +} +\concept{helpers} diff --git a/man/get_raw_variables.Rd b/man/get_raw_variables.Rd new file mode 100644 index 0000000..9693341 --- /dev/null +++ b/man/get_raw_variables.Rd @@ -0,0 +1,87 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{get_raw_variables} +\alias{get_raw_variables} +\title{Get list of unique raw variables for a database/cycle} +\usage{ +get_raw_variables(cycle, variables, variable_details, include_derived = FALSE) +} +\arguments{ +\item{cycle}{Character string specifying the database/cycle (e.g., "cycle1", +"cycle1_meds" for CHMS; "cchs2001" for CCHS).} + +\item{variables}{Data frame from variables.csv containing variable metadata.} + +\item{variable_details}{Data frame from variable_details.csv containing detailed specifications.} + +\item{include_derived}{Logical. Should derived variables be included? Default is FALSE +(since derived variables are computed from other variables, not in raw data).} +} +\value{ +Data frame with columns: +\itemize{ +\item variable_raw - Raw source variable name (unique) +\item variableType - "Categorical" or "Continuous" +\item harmonized_vars - Comma-separated list of harmonized variables that use this raw variable +\item n_harmonized - Count of how many harmonized variables use this raw variable +} +} +\description{ +Returns a data frame of unique raw (source) variables that should be generated +for a specific database/cycle. This is the correct approach for generating mock +data, as we want to create the raw source data, not the harmonized variables. +} +\details{ +This function: +\enumerate{ +\item Gets all variables available in the database/cycle using \code{\link{get_cycle_variables}} +\item Extracts unique raw variable names +\item Groups harmonized variables by their raw source +\item Returns one row per unique raw variable +} + +This is the correct approach because: +\itemize{ +\item Mock data should represent raw source data (before harmonization) +\item Each raw variable should appear exactly once +\item Multiple harmonized variables can derive from the same raw variable +} +} +\examples{ +\dontrun{ +# Load metadata +variables <- read.csv("inst/extdata/variables.csv") +variable_details <- read.csv("inst/extdata/variable-details.csv") + +# CHMS example +raw_vars <- get_raw_variables("cycle1", variables, variable_details) + +# CCHS example +raw_vars_cchs <- get_raw_variables("cchs2001", variables, variable_details) + +# Generate mock data from raw variables +for (i in 1:nrow(raw_vars)) { + var_raw <- raw_vars$variable_raw[i] + var_type <- raw_vars$variableType[i] + # Generate the raw variable... +} +} + +} +\seealso{ +\code{\link{get_cycle_variables}}, \code{\link{parse_variable_start}} + +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/get_variable_categories.Rd b/man/get_variable_categories.Rd new file mode 100644 index 0000000..3989b9b --- /dev/null +++ b/man/get_variable_categories.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/scalar_helpers.R +\name{get_variable_categories} +\alias{get_variable_categories} +\title{Extract categories from variable details} +\usage{ +get_variable_categories(var_details, include_na = FALSE) +} +\arguments{ +\item{var_details}{Data frame. Filtered variable_details rows} + +\item{include_na}{Logical. Include NA/missing codes (default FALSE)} +} +\value{ +Character vector of category values +} +\description{ +Extracts categorical values from variable_details recStart/recEnd columns. +Handles range notation, special codes, and missing code patterns. +} +\details{ +Handles recodeflow notation: +\itemize{ +\item Simple categories: "1", "2", "3" +\item Integer ranges: \code{"[7,9]"} → c("7", "8", "9") +\item Continuous ranges: "[18.5,25)" (kept as single value) +\item Special codes: "copy", "else" (EXCLUDED from mock data generation) +\item Missing codes: Identified by "NA" in recEnd +} + +Note: "else" is excluded because it acts as a garbage collector in +harmonization (recodes to NA::b), not a population category for generation. +} +\keyword{internal} diff --git a/man/get_variable_details.Rd b/man/get_variable_details.Rd new file mode 100644 index 0000000..5017459 --- /dev/null +++ b/man/get_variable_details.Rd @@ -0,0 +1,50 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{get_variable_details} +\alias{get_variable_details} +\title{Get variable details for specific variable} +\usage{ +get_variable_details(details, variable_name = NULL, uid = NULL) +} +\arguments{ +\item{details}{Data frame. Full details data (or NULL for fallback mode).} + +\item{variable_name}{Character. Variable name to filter (e.g., "ADL_01").} + +\item{uid}{Character. Alternative - filter by uid (e.g., "v_001").} +} +\value{ +Subset of details rows for this variable, sorted by uid_detail. +Returns NULL if details is NULL (signals fallback mode). +Returns empty data frame with warning if no matching rows. +} +\description{ +Filters details data frame to return only rows for a specific variable. +Handles NULL details (fallback mode) and provides consistent sorting. +} +\examples{ +\dontrun{ +details <- read_mock_data_config_details("details.csv") +var_details <- get_variable_details(details, variable_name = "ADL_01") + +# Fallback mode +var_details <- get_variable_details(NULL, variable_name = "ADL_01") +# Returns: NULL +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/get_variable_details_for_raw.Rd b/man/get_variable_details_for_raw.Rd new file mode 100644 index 0000000..70ea688 --- /dev/null +++ b/man/get_variable_details_for_raw.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/scalar_helpers.R +\name{get_variable_details_for_raw} +\alias{get_variable_details_for_raw} +\title{Scalar Variable Generation Helpers} +\usage{ +get_variable_details_for_raw( + var_raw, + cycle, + variable_details, + variables = NULL +) +} +\arguments{ +\item{var_raw}{Character. Raw variable name (e.g., "alc_11", "HGT_CM")} + +\item{cycle}{Character. Cycle identifier (e.g., "cycle1", "cchs2001")} + +\item{variable_details}{Data frame. Full variable_details metadata} + +\item{variables}{Data frame. Optional variables metadata (not used currently)} +} +\value{ +Data frame subset of variable_details for this variable + cycle +} +\description{ +Helper functions for scalar variable generation (single variables at a time). +Used by create_cat_var(), create_con_var(), create_date_var() when called +with individual variable parameters (var_raw, cycle, etc.) rather than +configuration data frames. +} +\details{ +These helpers work with recodeflow-style metadata (variables.csv + +variable_details.csv from cchsflow/chmsflow). +Get variable details for raw variable and cycle + +Filters variable_details to rows matching a specific raw variable name and cycle. +Handles multiple naming patterns from recodeflow packages. + +Tries three matching strategies in order: +\enumerate{ +\item Database-prefixed format: \code{"cycle::var_raw"} +\item Bracket format: \code{"[var_raw]"} with databaseStart filtering +\item Plain format: exact match on variableStart with cycle filtering +} +} +\keyword{internal} diff --git a/man/get_variables_by_role.Rd b/man/get_variables_by_role.Rd new file mode 100644 index 0000000..75b9cfa --- /dev/null +++ b/man/get_variables_by_role.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/config_helpers.R +\name{get_variables_by_role} +\alias{get_variables_by_role} +\title{Get variables by role} +\usage{ +get_variables_by_role(config, roles) +} +\arguments{ +\item{config}{Data frame. Configuration from read_mock_data_config().} + +\item{roles}{Character vector. Role(s) to filter for (e.g., c("enabled", "predictor")).} +} +\value{ +Data frame with subset of config rows matching any of the specified roles. +} +\description{ +Filters a MockData configuration to return only variables matching one or more roles. +The role column can contain comma-separated values (e.g., "predictor, outcome"), +so this function uses pattern matching to find all matching variables. +} +\details{ +This function handles comma-, semicolon-, or whitespace-separated role values +by exact token matching. A variable matches if any role token equals one of +the requested roles. + +Common role values: +\itemize{ +\item enabled: Variables to generate in mock data +\item predictor: Predictor variables for analysis +\item outcome: Outcome variables +\item confounder: Confounding variables +\item exposure: Exposure variables +\item intermediate: Intermediate/derived variables +\item table1_master, table1_sub: Table 1 display variables +\item metadata: Study metadata (dates, identifiers) +} +} +\examples{ +\dontrun{ +# Load configuration +config <- read_mock_data_config("inst/extdata/mock_data_config.csv") + +# Get all predictor variables +predictors <- get_variables_by_role(config, "predictor") + +# Get variables with multiple roles +outcomes <- get_variables_by_role(config, c("outcome", "exposure")) + +# Get Table 1 variables +table1_vars <- get_variables_by_role(config, c("table1_master", "table1_sub")) +} + +} +\seealso{ +Other configuration: +\code{\link{get_enabled_variables}()} +} +\concept{configuration} diff --git a/man/has_garbage.Rd b/man/has_garbage.Rd new file mode 100644 index 0000000..5887362 --- /dev/null +++ b/man/has_garbage.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{has_garbage} +\alias{has_garbage} +\title{Check if garbage is specified} +\usage{ +has_garbage(details_subset) +} +\arguments{ +\item{details_subset}{Data frame. Rows from details for one variable.} +} +\value{ +Logical. TRUE if garbage rows exist, FALSE otherwise. +} +\description{ +Quick check for presence of garbage rows (recEnd starts with "garbage_"). +} +\examples{ +\dontrun{ +if (has_garbage(details_subset)) { + values <- make_garbage(values, details_subset, "continuous") +} +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{make_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/identify_derived_vars.Rd b/man/identify_derived_vars.Rd new file mode 100644 index 0000000..3cb5c70 --- /dev/null +++ b/man/identify_derived_vars.Rd @@ -0,0 +1,93 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/identify_derived_vars.R +\name{identify_derived_vars} +\alias{identify_derived_vars} +\title{Identify derived variables using recodeflow patterns} +\usage{ +identify_derived_vars(variables, variable_details) +} +\arguments{ +\item{variables}{data.frame. Variable-level metadata with column: variable} + +\item{variable_details}{data.frame. Required. Detail-level metadata with +columns: variable, recStart, recEnd. Contains DerivedVar:: and Func:: +patterns that identify derived variables.} +} +\value{ +Character vector of derived variable names (may be empty if none found) +} +\description{ +Identifies derived variables using recodeflow metadata patterns in +variable_details. Derived variables are calculated from raw variables +(e.g., BMI from height/weight) and should NOT be generated as mock data. + +This function uses the recodeflow approach: derived variables are identified +by metadata patterns in variable_details, NOT by role column flags. +} +\details{ +\strong{Detection methods} (recodeflow patterns only): +\enumerate{ +\item \strong{DerivedVar:: pattern}: Variables with \verb{DerivedVar::} in recStart column +\itemize{ +\item Example: \code{recStart = "DerivedVar::[HWTGHTM, HWTGWTK]"} +\item Indicates variable is derived from listed raw variables +} +\item \strong{Func:: pattern}: Variables with \verb{Func::} in recEnd column +\itemize{ +\item Example: \code{recEnd = "Func::bmi_fun"} +\item Indicates transformation function applied to derive variable +} +} + +\strong{Why variable_details is required:} + +The recodeflow approach stores derivation logic in variable_details, not in +variables. The role column (if present) is NOT used for derived variable +detection. This ensures: +\itemize{ +\item Derivation logic is explicit (what variables, what function) +\item Metadata is self-documenting +\item Compatible with cchsflow and other recodeflow tools +} + +\strong{Note:} This function does NOT check role = "derived" even if present. +Derived status is determined solely by DerivedVar:: and Func:: patterns. +} +\examples{ +\dontrun{ +# BMI derived from height and weight +variables <- data.frame( + variable = c("height", "weight", "BMI_derived"), + variableType = c("Continuous", "Continuous", "Continuous"), + role = c("enabled", "enabled", "enabled"), # NO "derived" flag needed + stringsAsFactors = FALSE +) + +variable_details <- data.frame( + variable = c("height", "weight", "BMI_derived"), + recStart = c("[1.4,2.1]", "[45,150]", "DerivedVar::[height, weight]"), + recEnd = c("copy", "copy", "Func::bmi_fun"), + stringsAsFactors = FALSE +) + +identify_derived_vars(variables, variable_details) +# Returns: "BMI_derived" + +# ADL derived from 5 ADL items +variable_details_adl <- data.frame( + variable = c("ADL_01", "ADL_02", "ADL_03", "ADL_04", "ADL_05", "ADL_der"), + recStart = c(rep("1", 5), "DerivedVar::[ADL_01, ADL_02, ADL_03, ADL_04, ADL_05]"), + recEnd = c(rep("1", 5), "Func::adl_fun"), + stringsAsFactors = FALSE +) + +identify_derived_vars(variables, variable_details_adl) +# Returns: "ADL_der" +} + +} +\seealso{ +Other helpers: +\code{\link{get_raw_var_dependencies}()} +} +\concept{helpers} diff --git a/man/import_from_recodeflow.Rd b/man/import_from_recodeflow.Rd new file mode 100644 index 0000000..aaa7493 --- /dev/null +++ b/man/import_from_recodeflow.Rd @@ -0,0 +1,122 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/import_from_recodeflow.R +\name{import_from_recodeflow} +\alias{import_from_recodeflow} +\title{Import and convert recodeflow variables and variable details metadata files to MockData configuration format} +\usage{ +import_from_recodeflow( + variables_path, + variable_details_path, + role_filter = "mockdata", + database = NULL, + output_dir = "inst/extdata/" +) +} +\arguments{ +\item{variables_path}{Character. Path to recodeflow variables.csv file.} + +\item{variable_details_path}{Character. Path to recodeflow variable_details.csv file.} + +\item{role_filter}{Character. Role value to filter variables by. Only variables +with this role will be imported. Default is "mockdata". Use regex word boundary +matching to avoid partial matches (e.g., "mockdata" won't match "mockdata_test").} + +\item{database}{Character vector or NULL. Database identifier(s) to filter by. +If NULL (default), extracts all unique databases from variables.csv databaseStart +column. If specified, only imports variables that exist in the specified database(s).} + +\item{output_dir}{Character. Directory where output CSV files will be written. +Default is "inst/extdata/". Files will be named mock_data_config.csv and +mock_data_config_details.csv.} +} +\value{ +Invisible list with two data frames: config and details +} +\description{ +Converts recodeflow variables.csv and variable_details.csv files into +MockData configuration format (mock_data_config.csv and +mock_data_config_details.csv). Filters variables by role and optionally +by database. +} +\details{ +\subsection{Column Mapping}{ +\subsection{variables.csv -> mock_data_config.csv}{ + +Direct copy: variable, role, label, labelLong, section, subject, variableType, +units, version, description (to notes) + +Generated: +\itemize{ +\item uid: v_001, v_002, v_003, ... +\item position: 10, 20, 30, ... +\item source_database: extracted from databaseStart based on database filter +\item source_spec: basename of variables_path +\item last_updated: current date +\item mockDataLastUpdated: current date +\item seed: NA +\item rType: NA (user must fill in: integer/double/factor/date/logical/character) +\item garbage_low_prop, garbage_low_range, garbage_high_prop, garbage_high_range: NA +\item mockDataVersion, mockDataVersionNotes: NA +} +} + +\subsection{variable_details.csv -> mock_data_config_details.csv}{ + +Direct copy: variable, dummyVariable, catStartLabel (to catLabel), +catLabelLong, units, notes + +Mapped: +\itemize{ +\item recStart: copied from input recStart +\item recEnd: initialized to input recStart (user updates to: valid, distribution, mean, etc.) +} + +Generated: +\itemize{ +\item uid: looked up from config by variable name +\item uid_detail: d_001, d_002, d_003, ... +\item proportion: NA (user fills in - must sum to 1.0 per variable) +\item value: NA (user fills in distribution parameters) +\item sourceFormat: NA (user fills in for date variables) +} +} + +} + +\subsection{Database Filtering}{ + +When database parameter is specified, the function: +\enumerate{ +\item Filters variables.csv rows where databaseStart contains the specified database(s) +\item Filters variable_details.csv rows where databaseStart contains the specified database(s) +\item Sets source_database to the filtered database(s) in mock_data_config.csv +} +} +} +\examples{ +\dontrun{ +# Import all variables with role "mockdata" from all databases +import_from_recodeflow( + variables_path = "inst/extdata/cchs/variables_cchsflow_sample.csv", + variable_details_path = "inst/extdata/cchs/variable_details_cchsflow_sample.csv", + role_filter = "mockdata" +) + +# Import only from specific database +import_from_recodeflow( + variables_path = "inst/extdata/cchs/variables_cchsflow_sample.csv", + variable_details_path = "inst/extdata/cchs/variable_details_cchsflow_sample.csv", + role_filter = "mockdata", + database = "cchs2015_2016_p" +) + +# Import from multiple databases +import_from_recodeflow( + variables_path = "inst/extdata/cchs/variables_cchsflow_sample.csv", + variable_details_path = "inst/extdata/cchs/variable_details_cchsflow_sample.csv", + role_filter = "mockdata", + database = c("cchs2015_2016_p", "cchs2017_2018_p") +) +} + +} diff --git a/man/is_mock_spec.Rd b/man/is_mock_spec.Rd new file mode 100644 index 0000000..9fa73c1 --- /dev/null +++ b/man/is_mock_spec.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{is_mock_spec} +\alias{is_mock_spec} +\title{Check whether an object is a MockData specification} +\usage{ +is_mock_spec(x) +} +\arguments{ +\item{x}{Object to check.} +} +\value{ +Logical scalar. +} +\description{ +Check whether an object is a MockData specification +} +\examples{ +spec <- mock_spec() +is_mock_spec(spec) +is_mock_spec(list()) + +} diff --git a/man/make_garbage.Rd b/man/make_garbage.Rd new file mode 100644 index 0000000..e966803 --- /dev/null +++ b/man/make_garbage.Rd @@ -0,0 +1,64 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{make_garbage} +\alias{make_garbage} +\title{Make garbage} +\usage{ +make_garbage(values, details_subset, variable_type, seed = NULL) +} +\arguments{ +\item{values}{Vector. Generated values (already has valid + missing).} + +\item{details_subset}{Data frame. Rows from details (contains garbage_* rows).} + +\item{variable_type}{Character. "categorical", "continuous", "date", "survival".} + +\item{seed}{Integer. Optional random seed.} +} +\value{ +Vector with garbage applied. +} +\description{ +Applies garbage model to introduce realistic data quality issues. +Replaces some valid values with implausible values (garbage_low, garbage_high, +garbage_future, etc.). +} +\details{ +Two-step garbage model: +\enumerate{ +\item Identify valid value indices (not missing codes) +\item Sample from valid indices based on garbage proportions +\item Replace with garbage values +\item Ensure no overlap (use setdiff for sequential garbage application) +} + +Garbage types: +\itemize{ +\item garbage_low: Values below valid range (continuous, integer) +\item garbage_high: Values above valid range (continuous, integer) +\item garbage_future: Future dates (date, survival) +} +} +\examples{ +\dontrun{ +values <- c(23.5, 45.2, 7, 30.1, 9, 18.9, 25.6) +result <- make_garbage(values, details_subset, "continuous", seed = 123) +# Some valid values replaced with implausible values +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{sample_with_proportions}()} +} +\concept{mockdata-helpers} diff --git a/man/mock_categorical.Rd b/man/mock_categorical.Rd new file mode 100644 index 0000000..88ecd77 --- /dev/null +++ b/man/mock_categorical.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_categorical} +\alias{mock_categorical} +\title{Create a direct categorical mock-data specification} +\usage{ +mock_categorical( + name, + levels, + proportions = NULL, + rtype = "factor", + missing_codes = character(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = NULL, + model_hint = "auto", + spec_version = .mock_spec_version +) +} +\arguments{ +\item{name}{Variable name.} + +\item{levels}{Character vector of valid levels or codes.} + +\item{proportions}{Optional probabilities aligned to \code{levels}.} + +\item{rtype}{R output type. Defaults to \code{"factor"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Optional provenance metadata. Defaults to the direct API.} + +\item{model_hint}{Backend hint.} + +\item{spec_version}{Character version of the specification shape.} +} +\value{ +A validated \code{mock_spec} object containing one categorical variable. +} +\description{ +\code{mock_categorical()} is the simple direct API for categorical variables. It +returns a validated \code{mock_spec}; it does not generate data. +} +\details{ +Use \code{mock_categorical()} when specifying one variable directly in R code. Use +\code{\link[=mock_spec_categorical]{mock_spec_categorical()}} with \code{\link[=mock_spec]{mock_spec()}} when composing several variables +or when writing an adapter from another metadata source. +} +\examples{ +smoking_spec <- mock_categorical( + "smoking", + levels = c("never", "former", "current"), + proportions = c(0.5, 0.3, 0.2), + rtype = "character" +) +validate_mock_spec(smoking_spec) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_spec_categorical]{mock_spec_categorical()}} + +Other direct specification APIs: +\code{\link{mock_continuous}()}, +\code{\link{mock_date}()}, +\code{\link{mock_formula}()} +} +\concept{direct specification APIs} diff --git a/man/mock_continuous.Rd b/man/mock_continuous.Rd new file mode 100644 index 0000000..cab7ada --- /dev/null +++ b/man/mock_continuous.Rd @@ -0,0 +1,91 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_continuous} +\alias{mock_continuous} +\title{Create a direct continuous mock-data specification} +\usage{ +mock_continuous( + name, + range, + distribution = "uniform", + mean = NA_real_, + sd = NA_real_, + rtype = "double", + rate = NA_real_, + missing_codes = numeric(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = NULL, + model_hint = "auto", + spec_version = .mock_spec_version +) +} +\arguments{ +\item{name}{Variable name.} + +\item{range}{Numeric vector of length two giving the inclusive valid range.} + +\item{distribution}{Distribution name. Defaults to \code{"uniform"}.} + +\item{mean, sd}{Optional distribution parameters. Required when +\code{distribution = "normal"}.} + +\item{rtype}{R output type. Defaults to \code{"double"}.} + +\item{rate}{Rate parameter; required when \code{distribution = "exponential"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Optional provenance metadata. Defaults to the direct API.} + +\item{model_hint}{Backend hint.} + +\item{spec_version}{Character version of the specification shape.} +} +\value{ +A validated \code{mock_spec} object containing one continuous variable. +} +\description{ +\code{mock_continuous()} is the simple direct API for continuous variables. It +returns a validated \code{mock_spec}; it does not generate data. Generation +backends will consume this specification in a later v0.4 milestone. +} +\details{ +Use \code{mock_continuous()} when specifying one variable directly in R code. Use +\code{\link[=mock_spec_continuous]{mock_spec_continuous()}} with \code{\link[=mock_spec]{mock_spec()}} when composing several variables +or when writing an adapter from another metadata source. +} +\examples{ +age_spec <- mock_continuous( + "age", + range = c(18, 85), + distribution = "normal", + mean = 50, + sd = 12, + rtype = "integer" +) +validate_mock_spec(age_spec) + +wait_spec <- mock_continuous( + "wait", + range = c(0, 100), + distribution = "exponential", + rate = 0.1 +) +validate_mock_spec(wait_spec) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_spec_continuous]{mock_spec_continuous()}} + +Other direct specification APIs: +\code{\link{mock_categorical}()}, +\code{\link{mock_date}()}, +\code{\link{mock_formula}()} +} +\concept{direct specification APIs} diff --git a/man/mock_date.Rd b/man/mock_date.Rd new file mode 100644 index 0000000..e1e5f4b --- /dev/null +++ b/man/mock_date.Rd @@ -0,0 +1,70 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_date} +\alias{mock_date} +\title{Create a direct date mock-data specification} +\usage{ +mock_date( + name, + range, + rtype = "date", + source_format = "analysis", + missing_codes = character(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = NULL, + model_hint = "native-postprocess", + spec_version = .mock_spec_version +) +} +\arguments{ +\item{name}{Variable name.} + +\item{range}{Date vector of length two giving the inclusive valid date range.} + +\item{rtype}{R output type. Defaults to \code{"date"}.} + +\item{source_format}{Source-format hint. Defaults to \code{"analysis"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Optional provenance metadata. Defaults to the direct API.} + +\item{model_hint}{Backend hint.} + +\item{spec_version}{Character version of the specification shape.} +} +\value{ +A validated \code{mock_spec} object containing one date variable. +} +\description{ +\code{mock_date()} is the simple direct API for date variables. It returns a +validated \code{mock_spec}; it does not generate data. +} +\details{ +Date variables default to \code{model_hint = "native-postprocess"} because MockData +owns calendar-date generation and source-format conversion. Optional +backends may still generate other variables in the same specification. +} +\examples{ +interview_date_spec <- mock_date( + "interview_date", + range = as.Date(c("2001-01-01", "2005-12-31")) +) +validate_mock_spec(interview_date_spec) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_spec_date]{mock_spec_date()}} + +Other direct specification APIs: +\code{\link{mock_categorical}()}, +\code{\link{mock_continuous}()}, +\code{\link{mock_formula}()} +} +\concept{direct specification APIs} diff --git a/man/mock_formula.Rd b/man/mock_formula.Rd new file mode 100644 index 0000000..615c08d --- /dev/null +++ b/man/mock_formula.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_formula} +\alias{mock_formula} +\title{Create a direct formula-derived mock-data specification} +\usage{ +mock_formula( + name, + formula, + rtype = "double", + missing_codes = numeric(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = NULL, + model_hint = "auto", + spec_version = .mock_spec_version +) +} +\arguments{ +\item{name}{Variable name.} + +\item{formula}{Character scalar. An algebraic expression over other +variable names, e.g. \code{"weight / (height^2)"}.} + +\item{rtype}{R output type for the computed column. Defaults to \code{"double"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Optional provenance metadata. Defaults to the direct API.} + +\item{model_hint}{Backend hint.} + +\item{spec_version}{Character version of the specification shape.} +} +\value{ +A validated \code{mock_spec} object containing one formula variable. +} +\description{ +\code{mock_formula()} is the simple direct API for formula-derived variables. It +returns a validated \code{mock_spec}; it does not generate data. Formula +variables have no \code{range}/\code{levels}/\code{distribution} of their own — their +values come from evaluating \code{formula} over other variables in the same +specification once those have been generated; see +\code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}. +} +\details{ +Use \code{mock_formula()} when specifying one formula variable directly in R +code. Use \code{\link[=mock_spec_formula]{mock_spec_formula()}} with \code{\link[=mock_spec]{mock_spec()}} when composing several +variables or when writing an adapter from another metadata source. +} +\examples{ +bmi_spec <- mock_spec( + mock_spec_continuous("height", range = c(1.4, 2.1)), + mock_spec_continuous("weight", range = c(45, 150)), + mock_spec_formula("bmi", formula = "weight / (height^2)") +) +validate_mock_spec(bmi_spec) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_spec_formula]{mock_spec_formula()}}, \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}} + +Other direct specification APIs: +\code{\link{mock_categorical}()}, +\code{\link{mock_continuous}()}, +\code{\link{mock_date}()} +} +\concept{direct specification APIs} diff --git a/man/mock_spec.Rd b/man/mock_spec.Rd new file mode 100644 index 0000000..c4e750a --- /dev/null +++ b/man/mock_spec.Rd @@ -0,0 +1,70 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec} +\alias{mock_spec} +\title{Create a MockData specification} +\usage{ +mock_spec( + ..., + spec_version = .mock_spec_version, + provenance = list(adapter = "direct", source = "direct"), + model_hint = "auto", + validate = TRUE +) +} +\arguments{ +\item{...}{\code{mock_spec_variable} objects, or a single list of them. \code{NULL} +creates an empty specification.} + +\item{spec_version}{Character version of the specification shape.} + +\item{provenance}{List or character describing where the spec came from.} + +\item{model_hint}{Character backend hint. One of the supported MockData model +hints.} + +\item{validate}{Logical. If \code{TRUE}, validate the constructed specification +before returning it.} +} +\value{ +S3 object of class \code{mock_spec}. +} +\description{ +\code{mock_spec()} creates the normalized v0.4 specification object used by the +new architecture. Direct APIs and recodeflow adapters should both normalize +into this shape before validation and generation. +} +\details{ +The v0.4 API is layered. The \verb{mock_*()} helpers are the simple direct API for +one-variable specifications. The \verb{mock_spec_*()} constructors create variable +specifications that can be composed with \code{mock_spec()}. Metadata adapters, +such as \code{\link[=mock_spec_from_recodeflow]{mock_spec_from_recodeflow()}}, translate external metadata into the +same internal shape. Generation backends consume \code{mock_spec} objects rather +than re-reading user-facing metadata. +} +\examples{ +spec <- mock_spec( + mock_spec_continuous("age", range = c(18, 85), rtype = "integer"), + mock_spec_categorical( + "smoking", + levels = c("never", "former", "current"), + proportions = c(0.5, 0.3, 0.2) + ) +) +validate_mock_spec(spec) + +} +\seealso{ +\code{\link[=mock_continuous]{mock_continuous()}}, \code{\link[=mock_categorical]{mock_categorical()}}, \code{\link[=mock_date]{mock_date()}}, +\code{\link[=mock_spec_from_recodeflow]{mock_spec_from_recodeflow()}}, \code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, +\code{\link[=postprocess_mock_data]{postprocess_mock_data()}} + +Other mock specification APIs: +\code{\link{mock_spec_categorical}()}, +\code{\link{mock_spec_continuous}()}, +\code{\link{mock_spec_date}()}, +\code{\link{mock_spec_formula}()}, +\code{\link{mock_spec_from_recodeflow}()}, +\code{\link{mock_spec_survival}()} +} +\concept{mock specification APIs} diff --git a/man/mock_spec_categorical.Rd b/man/mock_spec_categorical.Rd new file mode 100644 index 0000000..ccd3fd6 --- /dev/null +++ b/man/mock_spec_categorical.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec_categorical} +\alias{mock_spec_categorical} +\title{Create a categorical variable specification} +\usage{ +mock_spec_categorical( + name, + levels, + proportions = NULL, + rtype = "factor", + missing_codes = character(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = "direct", + model_hint = "auto" +) +} +\arguments{ +\item{name}{Variable name.} + +\item{levels}{Character vector of valid levels or codes.} + +\item{proportions}{Optional probabilities aligned to \code{levels}.} + +\item{rtype}{R output type. Defaults to \code{"factor"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Provenance metadata.} + +\item{model_hint}{Backend hint.} +} +\value{ +A \code{mock_spec_variable} object. +} +\description{ +Create a categorical variable specification +} +\examples{ +smoking <- mock_spec_categorical( + "smoking", + levels = c("never", "former", "current"), + proportions = c(0.5, 0.3, 0.2), + rtype = "character" +) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_categorical]{mock_categorical()}} + +Other mock specification APIs: +\code{\link{mock_spec}()}, +\code{\link{mock_spec_continuous}()}, +\code{\link{mock_spec_date}()}, +\code{\link{mock_spec_formula}()}, +\code{\link{mock_spec_from_recodeflow}()}, +\code{\link{mock_spec_survival}()} +} +\concept{mock specification APIs} diff --git a/man/mock_spec_continuous.Rd b/man/mock_spec_continuous.Rd new file mode 100644 index 0000000..2a2a1f7 --- /dev/null +++ b/man/mock_spec_continuous.Rd @@ -0,0 +1,81 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec_continuous} +\alias{mock_spec_continuous} +\title{Create a continuous variable specification} +\usage{ +mock_spec_continuous( + name, + range, + distribution = "uniform", + mean = NA_real_, + sd = NA_real_, + rtype = "double", + rate = NA_real_, + missing_codes = numeric(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = "direct", + model_hint = "auto" +) +} +\arguments{ +\item{name}{Variable name.} + +\item{range}{Numeric vector of length two giving the inclusive valid range.} + +\item{distribution}{Distribution name. Defaults to \code{"uniform"}.} + +\item{mean, sd}{Optional distribution parameters.} + +\item{rtype}{R output type. Defaults to \code{"double"}.} + +\item{rate}{Rate parameter; required when \code{distribution = "exponential"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Provenance metadata.} + +\item{model_hint}{Backend hint.} +} +\value{ +A \code{mock_spec_variable} object. +} +\description{ +Create a continuous variable specification +} +\examples{ +age <- mock_spec_continuous( + "age", + range = c(18, 85), + distribution = "normal", + mean = 50, + sd = 12, + rtype = "integer" +) + +wait_spec <- mock_spec_continuous( + "wait", + range = c(0, 100), + distribution = "exponential", + rate = 0.1 +) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_continuous]{mock_continuous()}} + +Other mock specification APIs: +\code{\link{mock_spec}()}, +\code{\link{mock_spec_categorical}()}, +\code{\link{mock_spec_date}()}, +\code{\link{mock_spec_formula}()}, +\code{\link{mock_spec_from_recodeflow}()}, +\code{\link{mock_spec_survival}()} +} +\concept{mock specification APIs} diff --git a/man/mock_spec_date.Rd b/man/mock_spec_date.Rd new file mode 100644 index 0000000..52e4713 --- /dev/null +++ b/man/mock_spec_date.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec_date} +\alias{mock_spec_date} +\title{Create a date variable specification} +\usage{ +mock_spec_date( + name, + range, + rtype = "date", + source_format = "analysis", + missing_codes = character(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = "direct", + model_hint = "native-postprocess" +) +} +\arguments{ +\item{name}{Variable name.} + +\item{range}{Date vector of length two giving the inclusive valid date range.} + +\item{rtype}{R output type. Defaults to \code{"date"}.} + +\item{source_format}{Source-format hint. Defaults to \code{"analysis"}.} + +\item{missing_codes}{Explicit missing-code values.} + +\item{missing_proportions}{Missing-code probabilities aligned to +\code{missing_codes}.} + +\item{garbage_rules}{List of intentional invalid-value rules.} + +\item{provenance}{Provenance metadata.} + +\item{model_hint}{Backend hint.} +} +\value{ +A \code{mock_spec_variable} object. +} +\description{ +Create a date variable specification +} +\examples{ +interview_date <- mock_spec_date( + "interview_date", + range = as.Date(c("2001-01-01", "2005-12-31")) +) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_date]{mock_date()}} + +Other mock specification APIs: +\code{\link{mock_spec}()}, +\code{\link{mock_spec_categorical}()}, +\code{\link{mock_spec_continuous}()}, +\code{\link{mock_spec_formula}()}, +\code{\link{mock_spec_from_recodeflow}()}, +\code{\link{mock_spec_survival}()} +} +\concept{mock specification APIs} diff --git a/man/mock_spec_formula.Rd b/man/mock_spec_formula.Rd new file mode 100644 index 0000000..03e017a --- /dev/null +++ b/man/mock_spec_formula.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec_formula} +\alias{mock_spec_formula} +\title{Create a formula-derived variable specification} +\usage{ +mock_spec_formula( + name, + formula, + rtype = "double", + missing_codes = numeric(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = "direct", + model_hint = "auto" +) +} +\arguments{ +\item{name}{Variable name.} + +\item{formula}{Character scalar. An algebraic expression over other +variable names, e.g. \code{"weight / (height^2)"}.} + +\item{rtype}{R output type for the computed column. Defaults to \code{"double"}.} + +\item{missing_codes, missing_proportions, garbage_rules, provenance, model_hint}{As for other variable specifications; applied by post-processing.} +} +\value{ +A \code{mock_spec_variable} object of type \code{"formula"}. +} +\description{ +\code{mock_spec_formula()} describes a variable computed from other generated +variables by evaluating an algebraic expression (a \code{mockFormula}), rather +than sampled from a distribution. Evaluation happens in a restricted +environment exposing only the generated columns and a fixed allow-list of +base functions; see \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}}. +} +\seealso{ +\code{\link[=mock_formula]{mock_formula()}}, \code{\link[=evaluate_mock_formulas]{evaluate_mock_formulas()}} + +Other mock specification APIs: +\code{\link{mock_spec}()}, +\code{\link{mock_spec_categorical}()}, +\code{\link{mock_spec_continuous}()}, +\code{\link{mock_spec_date}()}, +\code{\link{mock_spec_from_recodeflow}()}, +\code{\link{mock_spec_survival}()} +} +\concept{mock specification APIs} diff --git a/man/mock_spec_from_recodeflow.Rd b/man/mock_spec_from_recodeflow.Rd new file mode 100644 index 0000000..ae07336 --- /dev/null +++ b/man/mock_spec_from_recodeflow.Rd @@ -0,0 +1,105 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec_recodeflow.R +\name{mock_spec_from_recodeflow} +\alias{mock_spec_from_recodeflow} +\title{Convert recodeflow metadata to a MockData specification} +\usage{ +mock_spec_from_recodeflow( + variables, + variable_details = NULL, + databaseStart = NULL, + role = "enabled", + exclude_derived = TRUE, + spec_version = .mock_spec_version, + model_hint = "auto" +) +} +\arguments{ +\item{variables}{Data frame or CSV path for recodeflow-style \code{variables} +metadata.} + +\item{variable_details}{Data frame, CSV path, or \code{NULL} for recodeflow-style +\code{variable_details} metadata.} + +\item{databaseStart}{Optional database/cycle token used to filter metadata by +exact comma-separated \code{databaseStart} values.} + +\item{role}{Character vector of role tokens to include. Defaults to +\code{"enabled"}. Use \code{NULL} to skip role filtering.} + +\item{exclude_derived}{Logical. If \code{TRUE}, exclude variables identified by +\verb{DerivedVar::} or \verb{Func::} rows in \code{variable_details}.} + +\item{spec_version}{Character version of the specification shape.} + +\item{model_hint}{Backend hint for the returned specification.} +} +\value{ +A validated \code{mock_spec} object. +} +\description{ +\code{mock_spec_from_recodeflow()} adapts recodeflow-style \code{variables} and +\code{variable_details} metadata into the normalized v0.4 \code{mock_spec} shape. It +returns a validated specification; it does not generate data. +} +\details{ +This adapter preserves recodeflow semantics instead of treating metadata as a +generic table. It uses exact role and \code{databaseStart} token matching, parses +valid ranges from \code{recStart}, classifies missing codes from \code{recEnd} values +that begin with \verb{NA::} (expanding an integer range such as \verb{[997,999]} into +its individual codes, with the row's proportion split equally), preserves +categorical levels and proportions, carries +\verb{garbage_*} settings into \code{garbage_rules}, and builds a survival date +(\code{\link[=mock_spec_survival]{mock_spec_survival()}}) from any date row that sets \code{anchor}, reading +\code{censored_by}, \code{followup_min}, \code{followup_max}, \code{event_prop}, \code{distribution}, +\code{shape} and \code{rate}. A date row with survival parameters but no \code{anchor} is +an error. + +By default, variables identified by \verb{DerivedVar::} or \verb{Func::} rows are +excluded because they should be evaluated after raw mock variables are +generated. Set \code{exclude_derived = FALSE} only when you want those rows to +appear in the adapter input and fail or be handled by later formula support. + +CSV path inputs are read with \code{stringsAsFactors = FALSE}, +\code{check.names = FALSE}, and \code{na.strings = c("", "NA")} so path-based inputs +preserve recodeflow column names and treat blank metadata cells like missing +values. The adapter normalizes \code{rType = "numeric"} to \code{"double"} to match +the v0.4 \code{mock_spec} type vocabulary. +} +\examples{ +variables <- data.frame( + variable = "age", + variableType = "Continuous", + rType = "integer", + role = "enabled", + distribution = "uniform" +) +details <- data.frame( + variable = "age", + recStart = "[18, 85]", + recEnd = "copy", + proportion = 1 +) +spec <- mock_spec_from_recodeflow(variables, details) +validate_mock_spec(spec) + +variables_file <- tempfile(fileext = ".csv") +details_file <- tempfile(fileext = ".csv") +write.csv(variables, variables_file, row.names = FALSE) +write.csv(details, details_file, row.names = FALSE) +spec_from_files <- mock_spec_from_recodeflow(variables_file, details_file) + +} +\seealso{ +\code{\link[=mock_spec]{mock_spec()}}, \code{\link[=mock_continuous]{mock_continuous()}}, \code{\link[=mock_categorical]{mock_categorical()}}, +\code{\link[=mock_date]{mock_date()}}, \code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, \code{\link[=postprocess_mock_data]{postprocess_mock_data()}} + +Other mock specification APIs: +\code{\link{mock_spec}()}, +\code{\link{mock_spec_categorical}()}, +\code{\link{mock_spec_continuous}()}, +\code{\link{mock_spec_date}()}, +\code{\link{mock_spec_formula}()}, +\code{\link{mock_spec_survival}()} +} +\concept{mock specification APIs} diff --git a/man/mock_spec_model_hints.Rd b/man/mock_spec_model_hints.Rd new file mode 100644 index 0000000..264c8ed --- /dev/null +++ b/man/mock_spec_model_hints.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec_model_hints} +\alias{mock_spec_model_hints} +\title{Model hints for MockData specifications} +\description{ +Model hints are lightweight backend guidance carried by \code{mock_spec} objects +and variables. They are not generation commands; generation backends may use +them to choose a sensible default path. +} +\details{ +Supported values: +\describe{ +\item{\code{auto}}{Let MockData choose the backend.} +\item{\code{native}}{Prefer the native MockData backend.} +\item{\code{simstudy}}{Prefer the optional \code{simstudy} backend.} +\item{\code{native-postprocess}}{Generate baseline values natively, then rely +on MockData post-processing such as date/source-format conversion.} +\item{\code{simstudy-or-native}}{Either backend is expected to be suitable.} +\item{\code{simstudy-advanced}}{Feature is expected to need advanced \code{simstudy} +support, such as correlations or survival durations.} +\item{\code{diagnostic-required}}{Generation/post-processing must preserve +diagnostics needed to interpret the result.} +} +} diff --git a/man/mock_spec_survival.Rd b/man/mock_spec_survival.Rd new file mode 100644 index 0000000..ee220c7 --- /dev/null +++ b/man/mock_spec_survival.Rd @@ -0,0 +1,84 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{mock_spec_survival} +\alias{mock_spec_survival} +\title{Create a survival date variable specification} +\usage{ +mock_spec_survival( + name, + anchor, + followup_min, + followup_max, + event_prop, + distribution = "uniform", + censored_by = NULL, + shape = NULL, + rate = NULL, + source_format = "analysis", + missing_codes = character(0), + missing_proportions = numeric(0), + garbage_rules = list(), + provenance = "direct", + model_hint = "native-postprocess" +) +} +\arguments{ +\item{name}{Variable name.} + +\item{anchor}{Name of the date variable this date is generated relative to.} + +\item{followup_min, followup_max}{Follow-up window in days after the anchor.} + +\item{event_prop}{Share of rows that receive an event, in \verb{[0, 1]}.} + +\item{distribution}{Follow-up time distribution: \code{"uniform"}, +\code{"exponential"}, or \code{"gompertz"}.} + +\item{censored_by}{Optional name of a competing survival variable with the +same anchor. Where that date is earlier than this one, this one becomes +\code{NA}.} + +\item{shape, rate}{Optional Gompertz parameters (defaults 0.1 and 0.0001). +The exponential distribution derives its rate from the follow-up window.} + +\item{source_format}{Output format. Only \code{"analysis"} (R \code{Date}) is +supported for survival dates.} + +\item{missing_codes, missing_proportions, garbage_rules, provenance, model_hint}{As for other variable specifications; applied by post-processing after +the survival rules.} +} +\value{ +A \code{mock_spec_variable} object of type \code{"survival"}. +} +\description{ +\code{mock_spec_survival()} describes a date generated relative to an anchor +(entry) date: \code{floor(n * event_prop)} rows receive a date a follow-up time +after the anchor, drawn within \verb{[followup_min, followup_max]} days, and the +rest are \code{NA} (censored). Survival variables are computed after baseline +generation by \code{\link[=generate_survival_dates]{generate_survival_dates()}}, so the anchor must be another +variable in the same \code{\link[=mock_spec]{mock_spec()}}. +} +\examples{ +spec <- mock_spec( + mock_spec_date("entry", range = as.Date(c("2001-01-01", "2005-12-31"))), + mock_spec_survival("death", anchor = "entry", + followup_min = 365, followup_max = 7300, event_prop = 0.2), + mock_spec_survival("event", anchor = "entry", + followup_min = 0, followup_max = 5475, event_prop = 0.3, + censored_by = "death") +) +validate_mock_spec(spec) + +} +\seealso{ +\code{\link[=generate_survival_dates]{generate_survival_dates()}}, \code{\link[=mock_spec_date]{mock_spec_date()}} + +Other mock specification APIs: +\code{\link{mock_spec}()}, +\code{\link{mock_spec_categorical}()}, +\code{\link{mock_spec_continuous}()}, +\code{\link{mock_spec_date}()}, +\code{\link{mock_spec_formula}()}, +\code{\link{mock_spec_from_recodeflow}()} +} +\concept{mock specification APIs} diff --git a/man/parse_range_notation.Rd b/man/parse_range_notation.Rd new file mode 100644 index 0000000..2d35fe2 --- /dev/null +++ b/man/parse_range_notation.Rd @@ -0,0 +1,93 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata-parsers.R +\name{parse_range_notation} +\alias{parse_range_notation} +\title{Parse range notation from variable_details} +\usage{ +parse_range_notation(range_string, range_type = "auto", expand_integers = TRUE) +} +\arguments{ +\item{range_string}{Character string containing range notation} + +\item{range_type}{Character. One of: +\itemize{ +\item "auto" (default): Auto-detect based on bracket notation and decimal values +\item "integer": Force integer range interpretation (generates sequence) +\item "continuous": Force continuous range interpretation +}} + +\item{expand_integers}{Logical. If TRUE and range_type is "integer", +returns all integers in the range as a vector} +} +\value{ +For continuous ranges: List with min, max, min_inclusive, max_inclusive +For integer ranges: List with min, max, values (if expand_integers=TRUE) +Returns NULL if parsing fails +} +\description{ +Parses recodeflow-standard range notation strings from variable_details.csv +(recodes column) into structured data for mock data generation. Supports +integer ranges, continuous ranges, special codes, and function calls. +} +\details{ +\strong{Range Notation Formats:} + +Supports both comma (recommended) and semicolon (compatibility) delimiters: +\itemize{ +\item Integer ranges: \verb{[7,9]} or \verb{[7;9]} → integers 7,8,9 +\item Continuous ranges: \verb{[18.5,25)} or \verb{[18.5;25)} → 18.5 ≤ x < 25 +\item Continuous ranges: \verb{[18.5,25]} or \verb{[18.5;25]} → 18.5 ≤ x ≤ 25 +\item Infinity ranges: \verb{[30,inf)} or \verb{[30;inf)} → x ≥ 30 +\item Date ranges: \verb{[2001-01-01;2005-12-31]} (semicolon recommended for dates) +\item Special codes: \verb{NA::a}, \verb{NA::b}, \code{copy}, \verb{else} (passed through unchanged) +\item Function calls: \code{Func::function_name} (passed through unchanged) +} + +\strong{Mathematical Bracket Notation:} +\itemize{ +\item \verb{[a,b]} or \verb{[a;b]} - Closed interval: a ≤ x ≤ b +\item \verb{[a,b)} or \verb{[a;b)} - Half-open interval: a ≤ x < b +\item \verb{(a,b]} or \verb{(a;b]} - Half-open interval: a < x ≤ b +\item \verb{(a,b)} or \verb{(a;b)} - Open interval: a < x < b +} + +\strong{Auto-Detection Logic:} +\itemize{ +\item Contains decimal values → continuous range +\item Uses mathematical bracket notation \verb{[a,b)} → continuous range +\item Simple \verb{[integer,integer]} → integer range (generates sequence) +\item Contains "inf" → continuous range +} + +[a;b)` - Half-open interval: a ≤ x < b +\itemize{ +\item `(a,b]: R:a;b)\%60\%20-\%20Half-open\%20interval:\%20a\%20\%E2\%89\%A4\%20x\%20\%3C\%20b\%0A-\%20\%60(a,b +[integer,integer]: R:integer,integer +} +} +\note{ +Adapted from cchsflow v4.0.0 (2025-07-27) - universal across recodeflow projects +} +\examples{ +# Integer ranges +parse_range_notation("[7,9]") +# Returns: list(min=7, max=9, values=c(7,8,9), type="integer") + +# Continuous ranges +parse_range_notation("[18.5,25)") +# Returns: list(min=18.5, max=25, min_inclusive=TRUE, max_inclusive=FALSE, type="continuous") + +parse_range_notation("[30,inf)") +# Returns: list(min=30, max=Inf, min_inclusive=TRUE, max_inclusive=FALSE, type="continuous") + +# Special cases +parse_range_notation("NA::a") # Returns: list(type="special", value="NA::a") +parse_range_notation("copy") # Returns: list(type="special", value="copy") +parse_range_notation("else") # Returns: list(type="special", value="else") + +} +\seealso{ +Other parsing-utilities: +\code{\link{parse_variable_start}()} +} +\concept{parsing-utilities} diff --git a/man/parse_variable_start.Rd b/man/parse_variable_start.Rd new file mode 100644 index 0000000..7bc7408 --- /dev/null +++ b/man/parse_variable_start.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata-parsers.R +\name{parse_variable_start} +\alias{parse_variable_start} +\title{Parse variableStart field to extract raw variable name} +\usage{ +parse_variable_start(variable_start, cycle) +} +\arguments{ +\item{variable_start}{Character string from variableStart field. Can contain +multiple database specifications separated by commas (e.g., "cycle1::age, cycle2::AGE").} + +\item{cycle}{Character string specifying the database/cycle to extract (e.g., "cycle1", "cchs2001").} +} +\value{ +Character string with the raw variable name, or NULL if not found. +} +\description{ +This function parses the \code{variableStart} field from variable_details metadata +and extracts the raw variable name for a specific database/cycle. It supports +recodeflow-standard formats: database-prefixed (\code{"database::varname"}), +bracket (\code{"[varname]"}), mixed, and plain formats. +} +\details{ +The function implements recodeflow-standard parsing strategies: +\enumerate{ +\item Database-prefixed format: \code{"database::varname"} - for database-specific names +\item Bracket format (whole string): \code{"[varname]"} - for database-agnostic names +\item Bracket format (segment): \code{"database1::var1, [var2]"} - \verb{[var2]} is DEFAULT for other databases +\item Plain format: \code{"varname"} - uses value as-is +} + +\strong{Important}: \verb{[variable]} represents the DEFAULT for all databases not explicitly +referenced with database:: notation. This reduces repetition when only one or a +few databases use different variable names. + +For DerivedVar format, returns NULL (requires custom derivation logic). +} +\examples{ +# Database-prefixed format +parse_variable_start("cycle1::height, cycle2::HEIGHT", "cycle1") +# Returns: "height" + +# Bracket format (database-agnostic) +parse_variable_start("[gen_015]", "cycle1") +# Returns: "gen_015" + +# Mixed format - [variable] is DEFAULT for databases not explicitly listed +parse_variable_start("cycle1::amsdmva1, [ammdmva1]", "cycle2") +# Returns: "ammdmva1" (uses default for cycle2) + +# Plain format +parse_variable_start("bmi", "cycle1") +# Returns: "bmi" + +# No match for specified database +parse_variable_start("cycle2::age", "cycle1") +# Returns: NULL + +} +\seealso{ +Other parsing-utilities: +\code{\link{parse_range_notation}()} +} +\concept{parsing-utilities} diff --git a/man/postprocess_mock_data.Rd b/man/postprocess_mock_data.Rd new file mode 100644 index 0000000..9836c3e --- /dev/null +++ b/man/postprocess_mock_data.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec_postprocess.R +\name{postprocess_mock_data} +\alias{postprocess_mock_data} +\title{Apply mock_spec post-processing rules} +\usage{ +postprocess_mock_data(data, spec, seed = NULL, diagnostics = TRUE) +} +\arguments{ +\item{data}{Data frame with one column for each variable in \code{spec}.} + +\item{spec}{A validated \code{mock_spec} object.} + +\item{seed}{Optional whole-number seed. Generation uses an isolated +L'Ecuyer-CMRG sub-stream and restores the caller's RNG state and kind on +exit, so output is reproducible for a given seed and package version +without perturbing the caller's RNG.} + +\item{diagnostics}{Logical. If \code{TRUE}, attach a \code{mockdata_diagnostics} +attribute to the returned data frame.} +} +\value{ +A data frame with post-processing applied. +} +\description{ +\code{postprocess_mock_data()} applies v0.4 \code{mock_spec} missing-code and +garbage-value rules to an already generated baseline data frame. It records a +\code{mockdata_diagnostics} attribute so downstream checks can distinguish values +assigned by post-processing from values that were drawn naturally by the +baseline generator. +} +\details{ +Missing-code diagnostics separate values that were naturally drawn as a +declared missing code (\code{preexisting_missing_code_indices}) from values that +were assigned by post-processing (\code{assigned_missing_indices}). Garbage rules +are applied only to rows that are not missing-code diagnostics, preserving the +audit trail for collision cases such as a valid category code that is also a +declared missing code. + +Garbage rules are applied in canonical order: \code{low}, then \code{high}, then any +other named rules in caller order. Each garbage rule is a named list with a +\code{proportion} field and a \code{range} field using MockData range notation, for +example \code{list(high = list(proportion = 0.05, range = "[150, 200]"))}. + +Diagnostics are stored as a data-frame attribute. Base R subsetting and some +downstream tools may drop attributes, so preserve the original post-processed +object when diagnostics are part of the audit trail. +} +\examples{ +spec <- mock_categorical( + "smoking", + levels = c("never", "former", "current"), + proportions = c(0.5, 0.3, 0.2), + rtype = "character", + missing_codes = "9", + missing_proportions = 0.05 +) +baseline <- generate_mock_data_native(spec, n = 20, seed = 1) +result <- postprocess_mock_data(baseline, spec, seed = 1) +attr(result, "mockdata_diagnostics")$variables$smoking + +} +\seealso{ +\code{\link[=generate_mock_data_native]{generate_mock_data_native()}}, \code{\link[=generate_mock_data_simstudy]{generate_mock_data_simstudy()}}, +\code{\link[=mock_spec]{mock_spec()}} + +Other mock generation APIs: +\code{\link{create_mock_data}()}, +\code{\link{generate_mock_data_native}()}, +\code{\link{generate_mock_data_simstudy}()}, +\code{\link{generate_survival_dates}()} +} +\concept{mock generation APIs} diff --git a/man/print.mockdata_validation_result.Rd b/man/print.mockdata_validation_result.Rd new file mode 100644 index 0000000..cd85b40 --- /dev/null +++ b/man/print.mockdata_validation_result.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{print.mockdata_validation_result} +\alias{print.mockdata_validation_result} +\title{Print MockData Validation Results} +\usage{ +\method{print}{mockdata_validation_result}(x, ...) +} +\arguments{ +\item{x}{mockdata_validation_result object} + +\item{...}{Additional arguments (unused)} +} +\description{ +Print MockData Validation Results +} diff --git a/man/read_mock_data_config.Rd b/man/read_mock_data_config.Rd new file mode 100644 index 0000000..c420581 --- /dev/null +++ b/man/read_mock_data_config.Rd @@ -0,0 +1,76 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_mock_data_config.R +\name{read_mock_data_config} +\alias{read_mock_data_config} +\title{Read and validate MockData configuration file defining variable specifications for mock data generation} +\usage{ +read_mock_data_config(config_path, validate = TRUE) +} +\arguments{ +\item{config_path}{Character. Path to mock_data_config.csv file.} + +\item{validate}{Logical. Whether to validate the configuration (default TRUE).} +} +\value{ +Data frame with configuration variables and their parameters, +sorted by position column. +} +\description{ +Reads a mock_data_config.csv file containing variable definitions for +mock data generation. Optionally validates the configuration against +schema requirements. +} +\details{ +The configuration file should have the following columns: + +\strong{Core columns:} +\itemize{ +\item uid: Unique identifier (v_001, v_002, ...) +\item variable: Variable name +\item role: Comma-separated role values (enabled, predictor, outcome, etc.) +\item label: Short label for tables +\item labelLong: Descriptive label +\item section: Primary grouping for Table 1 +\item subject: Secondary grouping +\item variableType: Data type (categorical, continuous, date, survival, character, integer) +\item units: Measurement units +\item position: Sort order (10, 20, 30...) +} + +\strong{Provenance columns:} +\itemize{ +\item source_database: Database identifier(s) from import +\item source_spec: Source specification file +\item version: Configuration version +\item last_updated: Date last modified +\item notes: Documentation +\item seed: Random seed for reproducibility +} + +The function performs the following processing: +\enumerate{ +\item Reads CSV file with read.csv() +\item Converts date columns to Date type +\item Sorts by position column +\item Validates if validate = TRUE +} +} +\examples{ +\dontrun{ +# Read configuration file +config <- read_mock_data_config( + "inst/extdata/mock_data_config.csv" +) + +# Read without validation +config <- read_mock_data_config( + "inst/extdata/mock_data_config.csv", + validate = FALSE +) + +# View structure +str(config) +head(config) +} + +} diff --git a/man/read_mock_data_config_details.Rd b/man/read_mock_data_config_details.Rd new file mode 100644 index 0000000..d277633 --- /dev/null +++ b/man/read_mock_data_config_details.Rd @@ -0,0 +1,78 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_mock_data_config_details.R +\name{read_mock_data_config_details} +\alias{read_mock_data_config_details} +\title{Read and validate MockData configuration details file containing distribution parameters and category proportions} +\usage{ +read_mock_data_config_details(details_path, validate = TRUE, config = NULL) +} +\arguments{ +\item{details_path}{Character. Path to mock_data_config_details.csv file.} + +\item{validate}{Logical. Whether to validate the details (default TRUE).} + +\item{config}{Data frame (optional). Configuration from read_mock_data_config() +for cross-validation of variable references.} +} +\value{ +Data frame with detail rows for each variable's distribution parameters. +} +\description{ +Reads a mock_data_config_details.csv file containing distribution parameters +and proportions for mock data generation. Optionally validates the details +against schema requirements and optionally against a config file. +} +\details{ +The details file should have the following columns: + +\strong{Link columns:} +\itemize{ +\item uid: Links to mock_data_config.csv via uid (variable-level) +\item uid_detail: Unique identifier for this detail row (d_001, d_002, ...) +\item variable: Variable name (denormalized for readability) +} + +\strong{Category/parameter columns:} +\itemize{ +\item dummyVariable: Recodeflow dummy variable identifier +\item recStart: Category value or range notation \verb{[min,max]} +\item catLabel: Short category label +\item catLabelLong: Long category label +\item units: Measurement units for this parameter +} + +\strong{Distribution parameters:} +\itemize{ +\item proportion: Proportion for this category (0-1) +\item value: Numeric value +\item range_min, range_max: Value ranges +\item notes: Implementation notes +} + +The function performs the following processing: +\enumerate{ +\item Reads CSV file with read.csv() +\item Converts numeric columns (proportion, value, ranges) +\item Validates if validate = TRUE +} +} +\examples{ +\dontrun{ +# Read details file +details <- read_mock_data_config_details( + "inst/extdata/mock_data_config_details.csv" +) + +# Read with cross-validation against config +config <- read_mock_data_config("inst/extdata/mock_data_config.csv") +details <- read_mock_data_config_details( + "inst/extdata/mock_data_config_details.csv", + config = config +) + +# View structure +str(details) +head(details) +} + +} diff --git a/man/sample_with_proportions.Rd b/man/sample_with_proportions.Rd new file mode 100644 index 0000000..9c09b07 --- /dev/null +++ b/man/sample_with_proportions.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mockdata_helpers.R +\name{sample_with_proportions} +\alias{sample_with_proportions} +\title{Sample with proportions} +\usage{ +sample_with_proportions(categories, proportions, n, seed = NULL) +} +\arguments{ +\item{categories}{Character or numeric vector. Category values.} + +\item{proportions}{Numeric vector. Proportions (same length, sum to 1.0).} + +\item{n}{Integer. Number of samples.} + +\item{seed}{Integer. Optional random seed.} +} +\value{ +Vector of length n with category assignments. +} +\description{ +Generates category assignments with specified proportions. +Handles NA proportions (uniform fallback) and validates inputs. +} +\examples{ +\dontrun{ +categories <- c("1", "2", "7", "9") +proportions <- c(0.4, 0.52, 0.03, 0.05) +assignments <- sample_with_proportions(categories, proportions, n = 1000) +} + +} +\seealso{ +Other mockdata-helpers: +\code{\link{apply_garbage}()}, +\code{\link{apply_missing_codes}()}, +\code{\link{apply_rtype_defaults}()}, +\code{\link{extract_distribution_params}()}, +\code{\link{extract_proportions}()}, +\code{\link{generate_garbage_values}()}, +\code{\link{get_cycle_variables}()}, +\code{\link{get_raw_variables}()}, +\code{\link{get_variable_details}()}, +\code{\link{has_garbage}()}, +\code{\link{make_garbage}()} +} +\concept{mockdata-helpers} diff --git a/man/validate_foreign_keys.Rd b/man/validate_foreign_keys.Rd new file mode 100644 index 0000000..3dd425b --- /dev/null +++ b/man/validate_foreign_keys.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_foreign_keys} +\alias{validate_foreign_keys} +\title{Validate Foreign Key Relationships} +\usage{ +validate_foreign_keys(variables, variable_details) +} +\description{ +Validate Foreign Key Relationships +} +\keyword{internal} diff --git a/man/validate_garbage.Rd b/man/validate_garbage.Rd new file mode 100644 index 0000000..c142c0d --- /dev/null +++ b/man/validate_garbage.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_garbage} +\alias{validate_garbage} +\title{Validate Garbage Data Parameters} +\usage{ +validate_garbage(variables) +} +\description{ +Validate Garbage Data Parameters +} +\keyword{internal} diff --git a/man/validate_mock_data_config.Rd b/man/validate_mock_data_config.Rd new file mode 100644 index 0000000..647d6f7 --- /dev/null +++ b/man/validate_mock_data_config.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_mock_data_config.R +\name{validate_mock_data_config} +\alias{validate_mock_data_config} +\title{Validate MockData configuration against schema requirements including required columns and unique identifiers} +\usage{ +validate_mock_data_config(config) +} +\arguments{ +\item{config}{Data frame. Configuration data read from mock_data_config.csv.} +} +\value{ +Invisible NULL. Stops with error message if validation fails. +} +\description{ +Validates a mock_data_config data frame against schema requirements. +Checks for required columns, unique variable names, valid role values, +and valid variableType values. +} +\details{ +Validation checks: + +\strong{Required columns:} +\itemize{ +\item uid, variable, role, variableType, position +} + +\strong{Uniqueness:} +\itemize{ +\item uid values must be unique +\item variable names must be unique +} + +\strong{Valid values:} +\itemize{ +\item role: Can contain enabled, predictor, outcome, confounder, exposure, +table1, metadata, intermediate (comma-separated) +\item variableType: categorical, continuous, date, survival, character, integer +} + +\strong{Safe NA handling:} +\itemize{ +\item Uses which() to handle NA values in logical comparisons +\item Prevents "missing value where TRUE/FALSE needed" errors +} +} +\examples{ +\dontrun{ +# Validate configuration +config <- read.csv("mock_data_config.csv", stringsAsFactors = FALSE) +validate_mock_data_config(config) +} + +} diff --git a/man/validate_mock_data_config_details.Rd b/man/validate_mock_data_config_details.Rd new file mode 100644 index 0000000..d24c81a --- /dev/null +++ b/man/validate_mock_data_config_details.Rd @@ -0,0 +1,84 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_mock_data_config_details.R +\name{validate_mock_data_config_details} +\alias{validate_mock_data_config_details} +\title{Validate MockData configuration details against schema requirements including proportion sums and parameter completeness} +\usage{ +validate_mock_data_config_details(details, config = NULL) +} +\arguments{ +\item{details}{Data frame. Details data read from mock_data_config_details.csv.} + +\item{config}{Data frame (optional). Configuration for cross-validation.} +} +\value{ +Invisible NULL. Stops with error message if validation fails. +} +\description{ +Validates a mock_data_config_details data frame against schema requirements. +Checks for required columns, valid proportions, proportion sums, parameter +requirements, and optionally validates links to config file. +} +\details{ +Validation checks: + +\strong{Required columns:} +\itemize{ +\item variable, recStart (always required) +\item recEnd (conditionally required when using missing data codes 6-9, 96-99) +\item uid, uid_detail (optional for simple examples) +} + +\strong{Conditional recEnd requirement:} +\itemize{ +\item recEnd column required when recStart contains missing codes (6-9, 96-99) +\item Enables classification: NA::a (skip), NA::b (missing), numeric (valid) +\item Without recEnd, missing vs. valid codes cannot be distinguished +} + +\strong{Uniqueness:} +\itemize{ +\item uid_detail values must be unique (if column present) +} + +\strong{Proportion validation:} +\itemize{ +\item Values must be in range \verb{[0, 1]} +\item Population proportions (valid + missing codes) must sum to 1.0 ±0.001 per variable +\item Garbage proportions (garbage_*) are excluded from sum +\item Auto-normalizes with warning if sum ≠ 1.0 +} + +\strong{Parameter validation:} +\itemize{ +\item Distribution-specific requirements: +\itemize{ +\item normal → mean + sd +\item gompertz → rate + shape +\item exponential → rate +\item poisson → rate +} +} + +\strong{Link validation (if config provided):} +\itemize{ +\item All uid values must exist in config$uid +} + +\strong{Flexible recEnd validation:} +\itemize{ +\item Warns but doesn't error on unknown recEnd values +} +} +\examples{ +\dontrun{ +# Validate details +details <- read.csv("mock_data_config_details.csv", stringsAsFactors = FALSE) +validate_mock_data_config_details(details) + +# Validate with cross-check against config +config <- read.csv("mock_data_config.csv", stringsAsFactors = FALSE) +validate_mock_data_config_details(details, config = config) +} + +} diff --git a/man/validate_mock_spec.Rd b/man/validate_mock_spec.Rd new file mode 100644 index 0000000..196d060 --- /dev/null +++ b/man/validate_mock_spec.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mock_spec.R +\name{validate_mock_spec} +\alias{validate_mock_spec} +\title{Validate a MockData specification} +\usage{ +validate_mock_spec(spec, n = NULL, strict = TRUE) +} +\arguments{ +\item{spec}{A \code{mock_spec} object.} + +\item{n}{Optional number of rows expected for generation. If supplied, must +be a non-negative whole number.} + +\item{strict}{Logical. If \code{TRUE}, invalid specs throw an error. If \code{FALSE}, +a validation result object is returned.} +} +\value{ +A \code{mock_spec_validation_result} object when valid or \code{strict = FALSE}. +} +\description{ +Validate a MockData specification +} +\examples{ +spec <- mock_spec(mock_spec_continuous("age", range = c(18, 85))) +validate_mock_spec(spec) + +result <- validate_mock_spec(list(), strict = FALSE) +result$valid + +} diff --git a/man/validate_mockdata_metadata.Rd b/man/validate_mockdata_metadata.Rd new file mode 100644 index 0000000..c43e7e0 --- /dev/null +++ b/man/validate_mockdata_metadata.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_mockdata_metadata} +\alias{validate_mockdata_metadata} +\title{Validate MockData Extension Fields} +\usage{ +validate_mockdata_metadata( + variables_path, + variable_details_path, + mode = "basic" +) +} +\arguments{ +\item{variables_path}{Path to variables.csv file} + +\item{variable_details_path}{Path to variable_details.csv file} + +\item{mode}{Validation mode: "basic" or "strict" (default: "basic")} +} +\value{ +Validation result object with errors, warnings, and info +} +\description{ +Validate MockData Extension Fields +} diff --git a/man/validate_proportions.Rd b/man/validate_proportions.Rd new file mode 100644 index 0000000..cf05a85 --- /dev/null +++ b/man/validate_proportions.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_proportions} +\alias{validate_proportions} +\title{Validate Proportion Sums} +\usage{ +validate_proportions(variable_details, mode) +} +\description{ +Validate Proportion Sums +} +\keyword{internal} diff --git a/man/validate_rtype.Rd b/man/validate_rtype.Rd new file mode 100644 index 0000000..b8d88f9 --- /dev/null +++ b/man/validate_rtype.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_rtype} +\alias{validate_rtype} +\title{Validate rType Values} +\usage{ +validate_rtype(variables) +} +\description{ +Validate rType Values +} +\keyword{internal} diff --git a/man/validate_uids.Rd b/man/validate_uids.Rd new file mode 100644 index 0000000..98118ac --- /dev/null +++ b/man/validate_uids.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_uids} +\alias{validate_uids} +\title{Validate UID Patterns} +\usage{ +validate_uids(variables, variable_details) +} +\description{ +Validate UID Patterns +} +\keyword{internal} diff --git a/man/validate_versioning.Rd b/man/validate_versioning.Rd new file mode 100644 index 0000000..621c1a2 --- /dev/null +++ b/man/validate_versioning.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/validate_mockdata_extensions.R +\name{validate_versioning} +\alias{validate_versioning} +\title{Validate MockData Versioning Fields} +\usage{ +validate_versioning(variables) +} +\description{ +Validate MockData Versioning Fields +} +\keyword{internal}