Skip to content

Commit 88c853d

Browse files
authored
Adding genCrossed and documentation (#253)
* Adding genCrossed and documentation * Update CITATION.cff --------- Co-authored-by: kgoldfeld <kgoldfeld@users.noreply.github.com>
1 parent c645c75 commit 88c853d

14 files changed

Lines changed: 282 additions & 11 deletions

CITATION.cff

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ message: 'To cite package "simstudy" in publications use:'
88
type: software
99
license: GPL-3.0-only
1010
title: 'simstudy: Simulation of Study Data'
11-
version: 0.9.2
11+
version: 0.9.2.9000
1212
doi: 10.21105/joss.02763
1313
identifiers:
1414
- type: doi
@@ -73,10 +73,13 @@ references:
7373
url: https://www.R-project.org/
7474
authors:
7575
- name: R Core Team
76+
website: https://ror.org/02zz1nj61
7677
institution:
7778
name: R Foundation for Statistical Computing
79+
website: https://ror.org/05qewa988
7880
address: Vienna, Austria
7981
year: '2026'
82+
doi: 10.32614/R.manuals
8083
version: '>= 4.1.0'
8184
- type: software
8285
title: data.table
@@ -137,10 +140,13 @@ references:
137140
notes: Imports
138141
authors:
139142
- name: R Core Team
143+
website: https://ror.org/02zz1nj61
140144
institution:
141145
name: R Foundation for Statistical Computing
146+
website: https://ror.org/05qewa988
142147
address: Vienna, Austria
143148
year: '2026'
149+
doi: 10.32614/R.manuals
144150
- type: software
145151
title: mvnfast
146152
abstract: 'mvnfast: Fast Multivariate Normal and Student''s t Methods'
@@ -209,7 +215,7 @@ references:
209215
title: fastglm
210216
abstract: 'fastglm: Fast and Stable Fitting of Generalized Linear Models using ''RcppEigen'''
211217
notes: Imports
212-
url: https://github.com/jaredhuling/fastglm
218+
url: https://jaredhuling.org/fastglm/
213219
repository: https://CRAN.R-project.org/package=fastglm
214220
authors:
215221
- family-names: Huling
@@ -336,10 +342,13 @@ references:
336342
notes: Suggests
337343
authors:
338344
- name: R Core Team
345+
website: https://ror.org/02zz1nj61
339346
institution:
340347
name: R Foundation for Statistical Computing
348+
website: https://ror.org/05qewa988
341349
address: Vienna, Austria
342350
year: '2026'
351+
doi: 10.32614/R.manuals
343352
- type: software
344353
title: gridExtra
345354
abstract: 'gridExtra: Miscellaneous Functions for "Grid" Graphics'
@@ -512,10 +521,13 @@ references:
512521
notes: Suggests
513522
authors:
514523
- name: R Core Team
524+
website: https://ror.org/02zz1nj61
515525
institution:
516526
name: R Foundation for Statistical Computing
527+
website: https://ror.org/05qewa988
517528
address: Vienna, Austria
518529
year: '2026'
530+
doi: 10.32614/R.manuals
519531
- type: software
520532
title: survival
521533
abstract: 'survival: Survival Analysis'

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,4 @@ LinkingTo:
7171
VignetteBuilder:
7272
knitr
7373
Encoding: UTF-8
74-
RoxygenNote: 7.3.3
74+
Config/roxygen2/version: 8.0.0

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export(genCorFlex)
3434
export(genCorGen)
3535
export(genCorMat)
3636
export(genCorOrdCat)
37+
export(genCrossed)
3738
export(genData)
3839
export(genDataDensity)
3940
export(genDummy)

NEWS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# simstudy (development version)
22

3+
## New feature
4+
5+
* Added `genCrossed()` to support simulation of crossed data structures,
6+
complementing `genCluster()` for nested data generation. The function
7+
creates Cartesian products of two or more data sets and adds a unique
8+
crossed identifier.
9+
10+
# Update
11+
312
* scenario_list() return type change: now returns a list of 1-row
413
data.frames (instead of vectors) to support mixed numeric/character
514
scenario values without coercion. If you were transposing scenario

R/group_data.R

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,104 @@ genCluster <- function(dtClust,
282282
return(dt[])
283283
}
284284

285+
#' @title Generate crossed data
286+
#'
287+
#' @description Create the Cartesian product of two or more data sets,
288+
#' preserving all variables from each input data set.
289+
#'
290+
#' @param ... Two or more data sets to be crossed. Each input may be a
291+
#' `data.frame` or `data.table`.
292+
#' @param id Name of the crossed id field. Defaults to `"cross_id"`.
293+
#'
294+
#' @return A `data.table` containing all combinations of rows from the input
295+
#' data sets. The crossed id is placed first and used as the key.
296+
#'
297+
#' @examples
298+
#' region_def <- defData(varname = "r_effect", formula = 0, variance = 1)
299+
#' mouse_def <- defData(varname = "m_effect", formula = 0, variance = 1)
300+
#'
301+
#' dd_region <- genData(20, region_def, id = "region")
302+
#' dd_mouse <- genData(8, mouse_def, id = "mouse")
303+
#'
304+
#' dd <- genCrossed(
305+
#' dd_mouse,
306+
#' dd_region,
307+
#' id = "mouse_region_id"
308+
#' )
309+
#'
310+
#' @export
311+
#' @concept group_data
312+
genCrossed <- function(..., id = "cross_id") {
313+
314+
# to "declare" variable
315+
316+
.cross_join_id <- NULL
317+
318+
####
319+
320+
dts <- list(...)
321+
322+
#### Check arguments
323+
324+
if (length(dts) < 2) {
325+
stop("at least two data sets must be provided", call. = FALSE)
326+
}
327+
328+
if (!is.character(id) || length(id) != 1) {
329+
stop("argument 'id' must be a single character string", call. = FALSE)
330+
}
331+
332+
#### Convert inputs to data.tables without modifying originals
333+
334+
dts <- lapply(dts, function(x) {
335+
data.table::copy(data.table::as.data.table(x))
336+
})
337+
338+
#### Check for duplicate column names across inputs
339+
340+
all_names <- unlist(lapply(dts, names), use.names = FALSE)
341+
342+
dup_names <- unique(all_names[duplicated(all_names)])
343+
344+
if (length(dup_names) > 0) {
345+
stop(
346+
"input data sets must not share column names: ",
347+
paste(dup_names, collapse = ", "),
348+
call. = FALSE
349+
)
350+
}
351+
352+
if (id %in% all_names) {
353+
stop("argument 'id' already exists as a column name", call. = FALSE)
354+
}
355+
356+
#### Create Cartesian product
357+
358+
for (i in seq_along(dts)) {
359+
dts[[i]][, .cross_join_id := 1L]
360+
}
361+
362+
# Sequentially merge all data sets to create Cartesian product
363+
364+
dt <- Reduce(
365+
function(x, y) {
366+
merge(x, y, by = ".cross_join_id", allow.cartesian = TRUE)
367+
},
368+
dts
369+
)
370+
371+
dt[, .cross_join_id := NULL]
372+
373+
#### Add crossed id, move it to first column, and set key
374+
375+
dt[, eval(id) := .I]
376+
377+
data.table::setcolorder(dt, c(id, setdiff(names(dt), id)))
378+
data.table::setkeyv(dt, id)
379+
380+
return(dt[])
381+
}
382+
285383
#' Generate event data using longitudinal data, and restrict output to time
286384
#' until the nth event.
287385
#'

R/simstudy-package.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ NULL
6363
#' def
6464
#' genData(5, def)
6565
#' @name distributions
66-
#' @aliases normal poisson noZeroPoisson binary binomial uniform
67-
#' categorical gamma beta negBinomial nonrandom exponential mixture
66+
#' @aliases normal poisson noZeroPoisson binary binomial uniform categorical gamma beta negBinomial nonrandom exponential mixture
6867
#' @md
6968
NULL
7069

man/addColumns.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/addCondition.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/addCorFlex.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/distributions.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)