Skip to content

Commit ecdfca6

Browse files
Keith GoldfeldKeith Goldfeld
authored andcommitted
Fix cor matrix rounding issues
1 parent 75154df commit ecdfca6

File tree

5 files changed

+55
-10
lines changed

5 files changed

+55
-10
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Type: Package
22
Package: simstudy
33
Title: Simulation of Study Data
44
Version: 0.9.0.9000
5-
Date: 2025-10-05
5+
Date: 2025-12-07
66
Authors@R:
77
c(person(given = "Keith",
88
family = "Goldfeld",

NEWS.md

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

3+
* Minor fix in `genCorMat` to address an issue where very small rounding differences
4+
could make correlation matrices appear non-symmetric, preventing some data generation.
5+
Matrices are now always properly symmetrized.
6+
37
# simstudy 0.9.0
48

59
## New features

R/generate_correlated_data.R

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,10 @@ genCorMat <- function(nvars, cors = NULL, rho = NULL, corstr = "cs", nclusters =
530530
}
531531

532532
assertPositiveSemiDefinite(corMat = cm)
533+
534+
cm <- ( cm + t(cm)) / 2 # ensure symmetry even with rounding errors - fixes CRAN error
533535
cm
536+
534537
}
535538

536539
.structCors <- function(x) {
@@ -549,6 +552,7 @@ genCorMat <- function(nvars, cors = NULL, rho = NULL, corstr = "cs", nclusters =
549552
cm <- .buildCorMat(nvars = nvars, corMatrix = NULL, corstr, rho)
550553
assertPositiveSemiDefinite(corMat = cm)
551554

555+
cm <- ( cm + t(cm)) / 2 # ensure symmetry even with rounding errors - fixes CRAN error
552556
cm
553557

554558
}
@@ -561,6 +565,8 @@ genCorMat <- function(nvars, cors = NULL, rho = NULL, corstr = "cs", nclusters =
561565

562566
cm <- cmLower + cmUpper
563567
diag(cm) <- 1
568+
569+
cm <- ( cm + t(cm)) / 2 # ensure symmetry even with rounding errors - fixes CRAN error
564570
cm
565571
}
566572

@@ -570,6 +576,7 @@ genCorMat <- function(nvars, cors = NULL, rho = NULL, corstr = "cs", nclusters =
570576
cm <- .fillCor(nvars, cors)
571577
assertPositiveSemiDefinite(corMat = cm)
572578

579+
cm <- ( cm + t(cm)) / 2 # ensure symmetry even with rounding errors - fixes CRAN error
573580
cm
574581

575582
}
@@ -588,6 +595,7 @@ genCorMat <- function(nvars, cors = NULL, rho = NULL, corstr = "cs", nclusters =
588595
}
589596

590597
assertPositiveSemiDefinite(corMat = cm)
598+
cm <- ( cm + t(cm)) / 2 # ensure symmetry even with rounding errors - fixes CRAN error
591599
cm
592600

593601
}
@@ -658,7 +666,6 @@ genCorMat <- function(nvars, cors = NULL, rho = NULL, corstr = "cs", nclusters =
658666
}
659667
}
660668

661-
cm <- ( cm + t(cm)) / 2 # ensure symmetry even with rounding errors - fixes CRAN error
662669
cm
663670

664671
}

tests/testthat/helper-gen_def.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
library(simstudy)
22
library(data.table)
3-
library(hedgehog, pos = 3)
3+
library(hedgehog)
44

55
# Generators:
66
# This file implements helper functions and generators used in property based

tests/testthat/test-conditions.R

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,50 @@ library(testthat)
22
library(simstudy)
33
library(data.table)
44

5-
test_that("conditions have correct class.", {
5+
# This test broke after simstudy version 0.9.0
6+
7+
# test_that("conditions have correct class.", {
8+
# skip_on_cran()
9+
# expect_error(stop(condition(c("error", "custom_Error"), "This is a custom error")),
10+
# class = c("error", "custom_Error")
11+
# )
12+
# expect_warning(warning(simstudy:::condition(c("warning", "custom_warning"), "This is a custom warning")),
13+
# class = c("warning", "custom_warning")
14+
# )
15+
# expect_message(message(simstudy:::condition(c("message", "custom_message"), "This is a custom message")),
16+
# class = c("message", "custom_message")
17+
# )
18+
# })
19+
20+
# Replacing with this test
21+
22+
test_that("simstudy custom condition classes are constructed correctly", {
623
skip_on_cran()
7-
expect_error(stop(condition(c("error", "custom_Error"), "This is a custom error")),
8-
class = c("error", "custom_Error")
24+
25+
# Test the condition constructor directly — this part is stable
26+
err_cond <- simstudy:::condition(
27+
c("error", "custom_Error"),
28+
"This is a custom error"
929
)
10-
expect_warning(warning(simstudy:::condition(c("warning", "custom_warning"), "This is a custom warning")),
11-
class = c("warning", "custom_warning")
30+
warn_cond <- simstudy:::condition(
31+
c("warning", "custom_warning"),
32+
"This is a custom warning"
1233
)
13-
expect_message(message(simstudy:::condition(c("message", "custom_message"), "This is a custom message")),
14-
class = c("message", "custom_message")
34+
msg_cond <- simstudy:::condition(
35+
c("message", "custom_message"),
36+
"This is a custom message"
1537
)
38+
39+
# Ensure the custom classes are present in the constructed object
40+
expect_s3_class(err_cond, "custom_Error")
41+
expect_s3_class(warn_cond, "custom_warning")
42+
expect_s3_class(msg_cond, "custom_message")
43+
44+
# Now test that signaling the condition yields the correct *base* class
45+
# This avoids fragile assumptions about how R internally rewrites classes.
46+
expect_error(stop(err_cond), class = "error")
47+
expect_warning(warning(warn_cond), class = "warning")
48+
expect_message(message(msg_cond), class = "message")
1649
})
1750

1851
test_that("pluralization works.", {
@@ -24,3 +57,4 @@ test_that("pluralization works.", {
2457
class = "simstudy::missingArgument"
2558
)
2659
})
60+

0 commit comments

Comments
 (0)