################################################################################ ### Tests for the InfinitySparseMatrix class ############################################################################### context("InfinitySparseMatrix tests") test_that("ISM Basics", { A <- makeInfinitySparseMatrix(c(1,2,3), cols = c(1,2, 2), rows = c(1,1,2)) expect_is(A, "InfinitySparseMatrix") expect_equal(dim(A), c(2,2)) # converting to the equivalent matrix m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2) expect_equivalent(as.matrix(A), m) # converting from a matrix to a ISM expect_equivalent(as.InfinitySparseMatrix(m), A) # and back again expect_equivalent(as.matrix(as.InfinitySparseMatrix(m)), m) # expect_equal(as(m, "InfinitySparseMatrix"), A) # a more complicated examples, missing an entire row/col w <- matrix(c(1,Inf,2, 3, Inf, 4), nrow = 3) B <- as.InfinitySparseMatrix(w) expect_equivalent(as.matrix(B), w) y <- matrix(c(1,2,3,Inf, Inf, Inf), nrow = 3) D <- as.InfinitySparseMatrix(y) expect_equivalent(as.matrix(D), y) # the as() technique should be equivalent expect_equivalent(as(D, "matrix"), y) expect_equivalent(A, as(m, "InfinitySparseMatrix")) # NAs, NaNs are effectively Inf's mm <- m mm[is.infinite(m)] <- NA expect_equivalent(as.InfinitySparseMatrix(mm), as.InfinitySparseMatrix(m) ) mm[is.infinite(m)] <- NaN expect_equivalent(as.InfinitySparseMatrix(mm), as.InfinitySparseMatrix(m) ) }) test_that("ISM Handles Names", { m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2, dimnames = list(treated = c("A", "B"), control = c("C", "D"))) expect_equal(as.matrix(as(m, "InfinitySparseMatrix")), m) A <- makeInfinitySparseMatrix(c(1,2,3), rows = c(1,1,2), cols = c(1,2,2)) expect_true(is.null(dimnames(A))) dms <- list(treated = c("A", "B"), control = c("x", "y")) dimnames(A) <- dms expect_equal(dimnames(A), dms) dimnames(m) <- dms expect_equal(as.matrix(A), m) dimnames(A) <- NULL expect_null(dimnames(A)) }) test_that("Math Ops", { m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2) A <- as.InfinitySparseMatrix(m) # scalar math expect_equivalent(as.matrix(A + 1), m + 1) expect_equivalent(as.matrix(A - 1), m - 1) expect_equivalent(as.matrix(A * 2), m * 2) expect_equivalent(as.matrix(A / 2), m / 2) # matrix element wise math expect_equivalent(as.matrix(A + A), m + m) # Inf - Inf or Inf / Inf gives NA (Inf) mm <- m - m mm[is.na(mm)] <- Inf md <- m / m md[is.na(md)] <- Inf expect_equivalent(as.matrix(A - A), mm) expect_equivalent(as.matrix(A * A), m * m) expect_equivalent(as.matrix(A / A), md) # Inf * 0 gives NaN (Inf) m0 <- m * 0 m0[is.nan(m0)] <- Inf expect_equivalent(as.matrix(A * 0), m0) # The harder case is when the matrix has non-identical row/col ids q <- matrix(c(1, 2, Inf, 4), nrow = 2, ncol = 2) B <- as.InfinitySparseMatrix(q) expect_equivalent(as.matrix(A + B), m + q) expect_equivalent(as.matrix(A * B), m * q) # TODO, make up temp matrices for sub and div # dense + sparse => sparse Aq <- A + q expect_is(Aq, "InfinitySparseMatrix") expect_equivalent(as.matrix(Aq), m + q) # make sure it works the other direction (and with mult) qA <- q * A expect_is(qA, "InfinitySparseMatrix") expect_equivalent(as.matrix(qA), q * m) # names should be sticky across arithmatic # TODO, math should reorder by names in case that changes things colnames(A) <- paste("C", 1:2, sep = "") rownames(A) <- paste("T", 1:2, sep = "") colnames(q) <- paste("C", 1:2, sep = "") rownames(q) <- paste("T", 1:2, sep = "") Aq <- A + q expect_equal(colnames(Aq), c("C1", "C2")) expect_equal(rownames(Aq), c("T1", "T2")) # math ops over two matrices with same rows/names bu in different orders B <- as.InfinitySparseMatrix(q) # q got rownames later q.reordered <- q[,2:1] C <- as.InfinitySparseMatrix(q.reordered) expect_equal(colnames(C), rev(colnames(B))) expect_equal(A + C, A + B) }) test_that("Math ops with vectors", { # Small matrix with manual calculation m <- matrix(c(1, 4, 2, 3), nrow = 2, ncol = 2) A <- optmatch:::as.InfinitySparseMatrix(m) v <- 1:2 expect_true(all.equal(attributes(A), attributes(A/v))) expect_true(all.equal(attributes(A), attributes(A*v))) expect_true(all.equal(attributes(A), attributes(A-v))) expect_true(all.equal(attributes(A), attributes(A+v))) expect_true(all.equal(attributes(A), attributes(A^v))) expect_true(all.equal(attributes(A), attributes(A%%v))) expect_true(all.equal(attributes(A), attributes(A%/%v))) expect_true(all.equal(attributes(A), attributes(v/A))) expect_true(all.equal(attributes(A), attributes(v*A))) expect_true(all.equal(attributes(A), attributes(v-A))) expect_true(all.equal(attributes(A), attributes(v+A))) expect_true(all.equal(attributes(A), attributes(v^A))) expect_true(all.equal(attributes(A), attributes(v%%A))) expect_true(all.equal(attributes(A), attributes(v%/%A))) expect_true(all(as.vector(A/v) == c(1,2,2,3/2))) expect_true(all(as.vector(A*v) == c(1,8,2,6))) expect_true(all(as.vector(A+v) == c(2,6,3,5))) expect_true(all(as.vector(A-v) == c(0,2,1,1))) expect_true(all(as.vector(A^v) == c(1,16,2,9))) expect_true(all(as.vector(A%%v) == c(0,0,0,1))) expect_true(all(as.vector(A%/%v) == c(1,2,2,1))) expect_true(all(as.vector(v/A) == c(1,1/2, 1/2, 2/3))) expect_true(all(as.vector(v*A) == c(1,8,2,6))) expect_true(all(as.vector(v+A) == c(2,6,3,5))) expect_true(all(as.vector(v-A) == c(0,-2,-1,-1))) expect_true(all(as.vector(v^A) == c(1,16,1,8))) expect_true(all(as.vector(v%%A) == c(0,2,1,2))) expect_true(all(as.vector(v%/%A) == c(1,0,0,0))) # Logical operations m2 <- m m2[1,2] <- Inf A2 <- optmatch:::as.InfinitySparseMatrix(m2) expect_is(A2 <= c(1,3), "InfinitySparseMatrix") expect_equal(as.vector(A2 <= c(1,3)), c(T, F, T)) expect_equal(as.vector(c(1,3) >= A2), c(T, F, T)) # BlockedInfinitySparseMatrix x <- c(rep(1,4), rep(2,2), rep(3,5)) set.seed(1) y <- runif(11) z <- c(0,0,1,0,1,0,1,1,0,0,0) A <- match_on(z~y, within=exactMatch(z~x)) m <- as.matrix(A) v <- 1:5 # There's some dimensionality issues here, so we'll get lots of "not # a multiple" warnings. expect_warning({expect_true(all(as.matrix(A/v) == m/v)) expect_true(all(as.matrix(A*v) == m*v)) expect_true(all(as.matrix(A+v) == m+v)) expect_true(all(as.matrix(A-v) == m-v)) expect_true(all(as.matrix(A^v) == m^v)) expect_true(all(as.matrix(A%%v) == m%%v, na.rm=TRUE)) expect_true(all(as.matrix(A%/%v) == m%/%v, na.rm=TRUE)) vm <- v/m vm[!is.finite(as.matrix(A))] <- Inf expect_true(all(as.matrix(v/A) == vm)) expect_true(all(as.matrix(v*A) == v*m)) expect_true(all(as.matrix(v+A) == v+m)) vm <- v-m vm[!is.finite(as.matrix(A))] <- Inf expect_true(all(as.matrix(v-A) == vm)) vm <- v^m vm[!is.finite(as.matrix(A))] <- Inf expect_true(all(as.matrix(v^A) == vm))}, "not a multiple") # R 3.7 changed the behavior of c%%Inf. See #179. # Checking only for equality of finite entries vmodA <- as.matrix(v%%A) vintdivA <- as.matrix(v%/%A) expect_warning({ expect_true(all(vmodA[is.finite(vmodA)] == (v%%m)[is.finite(m)], na.rm = TRUE)) expect_true(all(vintdivA[is.finite(vintdivA)] == (v%/%m)[is.finite(m)], na.rm = TRUE)) }, "not a multiple") # Error on non-numeric input expect_error("a"*A, "non-numeric") }) test_that("#190: agreement in dimension names", { m1 <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2) m1 <- as.InfinitySparseMatrix(m1) m2 <- matrix(c(1, 2, Inf, 4), nrow = 2, ncol = 2) m2 <- as.InfinitySparseMatrix(m2) # No names, no error expect_null(dimnames(m1+m2)) # Only one matrix has a name, should warn colnames(m1) <- paste("C", 1:2, sep = "") rownames(m1) <- paste("T", 1:2, sep = "") expect_warning(m1 + m2, "One matrix has dimnames and the other does not") # Both have names but disagree colnames(m2) <- paste("C", 1:2, sep = "") rownames(m2) <- paste("T", 2:3, sep = "") expect_error(m1 + m2, "rows in first matrix: T1") expect_error(m1 + m2, "rows in second matrix: T3") expect_error(m2 + m1, "rows in first matrix: T3") expect_error(m2 + m1, "rows in second matrix: T1") # Testing other binops expect_error(m1 - m2) expect_error(m1 * m2) expect_error(m1 / m2) # Same names but different order should be fine rownames(m2) <- paste("T", 2:1, sep = "") expect_equal(dim(m1 + m2), c(2,2)) expect_equal(dim(m2 + m1), c(2,2)) # Same names should be fine rownames(m2) <- paste("T", 1:2, sep = "") expect_equal(dim(m1 + m2), c(2,2)) expect_equal(dim(m2 + m1), c(2,2)) }) test_that("Subsetting", { m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2) rownames(m) <- c("A", "B") colnames(m) <- c("C", "D") A <- as.InfinitySparseMatrix(m) res.sub <- subset(A, c(TRUE, FALSE)) expect_equal(res.sub@.Data, c(1, 2)) expect_equal(res.sub@cols, c(1,2)) expect_equal(res.sub@rows, c(1,1)) expect_equal(dim(res.sub), c(1,2)) # #204 subseting without row/col names works with Infs A <- as.InfinitySparseMatrix(matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2)) res.sub <- subset(A, c(TRUE, TRUE), c(TRUE, FALSE)) expect_equal(res.sub@.Data, c(1)) expect_equal(res.sub@cols, c(1)) expect_equal(res.sub@rows, c(1)) expect_equal(dim(res.sub), c(2,1)) }) test_that("cbinding ISMs and matrices", { m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2) rownames(m) <- c("A", "B") colnames(m) <- c("C", "D") A <- as.InfinitySparseMatrix(m) # Expect warnings for duplicate column names expect_warning(res.AA <- cbind(A, A)) expect_equal(length(res.AA), 6) expect_equal(dim(res.AA), c(2, 4)) # and the names should be uniquified (that's a word, really!) expect_equal(length(unique(colnames(res.AA))), 4) # same for matrices expect_warning(res.Am <- cbind(A, m)) expect_equal(res.Am, res.AA) # flipped name order shouldn't matter m2 <- m rownames(m2) <- c("B", "A") expect_warning(res.Am2 <- cbind(A, m2)) m4 <- matrix(1, nrow = 2, ncol = 3) rownames(m4) <- c("A", "C") colnames(m4) <- c("X", "Y", "Z") expect_error(cbind(A, m4)) m5 <- matrix(1, nrow = 3, ncol = 2) rownames(m5) <- c("A", "B", "C") colnames(m5) <- c("X", "Y") expect_error(cbind(A, m5)) }) test_that("rbinding ISMs and matrices", { m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2) rownames(m) <- c("A", "B") colnames(m) <- c("C", "D") A <- as.InfinitySparseMatrix(m) # Expect warnings for duplicate row names expect_warning(res.AA <- rbind(A, A)) expect_equal(length(res.AA), 6) expect_equal(dim(res.AA), c(4,2)) # and the names should be uniquified (that's a word, really!) expect_equal(length(unique(rownames(res.AA))), 4) expect_warning(res.Am <- rbind(A, m), "share row names") expect_equal(res.Am, res.AA) # flipped column names should not matter m2 <- m colnames(m2) <- c("D", "C") expect_warning(res.Am2 <- rbind(A, m2)) m4 <- matrix(1, nrow = 2, ncol = 2) rownames(m4) <- c("A", "B") colnames(m4) <- c("X", "Y") expect_error(rbind(A, m4)) m5 <- matrix(1, nrow = 2, ncol = 3) rownames(m5) <- c("A", "B") colnames(m5) <- c("C", "D", "E") expect_error(rbind(A, m5)) }) test_that("t(ransform) function", { # set up the names on the dims backwards to that when # we call t(m), everything is labeled properly m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2, dimnames = list(control = c("A", "B"), treated = c("C", "D"))) A <- as.InfinitySparseMatrix(m) expect_equal(as.matrix(t(A)), t(m)) }) ################################################################################ # Tests for the BlockedISM subclass ################################################################################ test_that("BlockedISM addition", { Z <- rep(c(0,1), 8) B1 <- rep(1:4, each = 4) B2 <- rep(c(0,1), each = 8) res.b1 <- exactMatch(Z ~ B1) res.b2 <- exactMatch(Z ~ B2) res.b1b1 <- res.b1 + res.b1 expect_equal(res.b1b1@groups, res.b1@groups) # should use the smaller of the two's groups res.b2b1 <- res.b2 + res.b1 expect_equal(res.b2b1@groups, res.b1@groups) expect_is(res.b2 + 1, "BlockedInfinitySparseMatrix") # Per #190, combining an ISM with name and ISM without names should warn, # so removing names here. expect_warning(res.b2 + matrix(1, nrow = 8, ncol = 8)) dimnames(res.b2) <- NULL expect_is(res.b2 + matrix(1, nrow = 8, ncol = 8), "BlockedInfinitySparseMatrix") expect_is(matrix(1, nrow = 8, ncol = 8) + res.b2, "BlockedInfinitySparseMatrix") }) test_that("Get subproblem size of each block", { Z <- rep(c(0,1), 8) B1 <- c(rep('a',3),rep('b', 3), rep('c', 6), rep('d', 4)) B2 <- c(rep(0, 7), rep(1, 9)) B3 <- c('a', rep('b', 15)) # group a has no treatment. res.b1 <- exactMatch(Z ~ B1) res.b2 <- exactMatch(Z ~ B2) res.b3 <- exactMatch(Z ~ B3) expect_equal(as.list(subdim(res.b1)), list('a' = c(1, 2),'b' = c(2, 1),'c' = c(3, 3),'d' = c(2, 2))) expect_equivalent(as.list(subdim(res.b2)), list('0' = c(3, 4),'1' = c(5, 4))) expect_equal(as.list(subdim(res.b3)), list('b' = c(8, 7))) m <- matrix(c(1,Inf, 2, 3), nrow = 2, ncol = 2, dimnames = list(control = c("A", "B"), treated = c("C", "D"))) a <- as.InfinitySparseMatrix(m) # subdim on a matrix or non-blocked ISM is equivalent to calling dim expect_equivalent(as.list(subdim(m)), list(dim(m))) expect_equivalent(as.list(subdim(a)), list(dim(a))) # test on DenseMatrix W <- rnorm(16) m <- match_on(Z ~ W) expect_equivalent(as.list(subdim(m)), list(dim(m))) }) test_that("subdim drops blocks w/ no possible matches (#129)", { Z <- rep(c(0,1), 4) B <- rep(c("a", "b"), each=4) x <- c((1L:4L)/10, (1L:4L) *10) m <- exactMatch(Z ~ B) m <- match_on(Z ~ x, within=m, method="euclidean") m <- caliper(m, width=1) # Prior to #129, subdim(m) would have been `list(a=c(2,2),b=c(2,2)` expect_equivalent(subdim(m), list(c(2,2))) }) test_that("ISM sorting", { X <- makeInfinitySparseMatrix(data = c(6,5,2,3,1), cols = c(2,1,2,1,1), rows = c(3,3,1,2,1)) # Output should still be ISM expect_is(X, "InfinitySparseMatrix") expect_is(sort(X), "InfinitySparseMatrix") expect_is(sort(X, byCol=TRUE), "InfinitySparseMatrix") X.rows <- sort(X, byCol=FALSE) X.cols <- sort(X, byCol=TRUE) expect_identical(dim(X.cols), dim(X)) expect_identical(dim(X.rows), dim(X)) expect_identical(as.matrix(X.cols), as.matrix(X)) expect_identical(as.matrix(X.rows), as.matrix(X)) # pairwise coords should be sorted, e.g. # (1,1), (1,2), (2,1), (2,2) # In original X, this is not true. coordrc <- as.numeric(paste(attr(X, "rows"), attr(X, "cols"), sep="")) coordcr <- as.numeric(paste(attr(X, "cols"), attr(X, "rows"), sep="")) expect_true(is.unsorted(coordrc)) expect_true(is.unsorted(coordcr)) # When sorting by column, then when looking at column/row it should be # true. coordrc.sortcols <- as.numeric(paste(attr(X.cols, "rows"), attr(X.cols, "cols"), sep="")) coordcr.sortcols <- as.numeric(paste(attr(X.cols, "cols"), attr(X.cols, "rows"), sep="")) expect_true(is.unsorted(coordrc.sortcols)) expect_true(!is.unsorted(coordcr.sortcols)) # Ditto when sorting by row & looking at row first. coordrc.sortrows <- as.numeric(paste(attr(X.rows, "rows"), attr(X.rows, "cols"), sep="")) coordcr.sortrows <- as.numeric(paste(attr(X.rows, "cols"), attr(X.rows, "rows"), sep="")) expect_true(!is.unsorted(coordrc.sortrows)) expect_true(is.unsorted(coordcr.sortrows)) # Checking for bad input on byCol expect_silent(sort(X, byCol=1)) expect_error(sort(X, byCol="a")) expect_error(sort(X, byCol=c(1,1))) # Checking argument `decreasing` X.rows <- sort(X, byCol=FALSE, decreasing=TRUE) X.cols <- sort(X, byCol=TRUE, decreasing=TRUE) expect_identical(as.matrix(X.rows), as.matrix(X)) expect_identical(as.matrix(X.cols), as.matrix(X)) coordrc.sortcols <- as.numeric(paste(attr(X.cols, "rows"), attr(X.cols, "cols"), sep="")) coordcr.sortcols <- as.numeric(paste(attr(X.cols, "cols"), attr(X.cols, "rows"), sep="")) expect_true(is.unsorted(coordrc.sortcols)) # to check sorting, reverse the order. expect_true(!is.unsorted(rev(coordcr.sortcols))) data(nuclearplants) m <- match_on(pr ~ cost, data=nuclearplants, caliper=1) m.rows <- sort(m, byCol=FALSE) m.cols <- sort(m, byCol=TRUE) # by default, ISM's are row dominant, so resorting by row should not # have any impact. expect_identical(m, m.rows) # However, sorting by column should change the internals, but not # externals. expect_identical(as.matrix(m), as.matrix(m.cols)) expect_false(identical(m, m.cols)) # Double-sorting expect_identical(m, sort(m.cols)) }) test_that("BISM sorting", { b <- makeInfinitySparseMatrix(c(1,2,3,4,5,6), cols=c(1,2,2,3,4,3), rows=c(1,1,2,3,3,4), colnames=c("1", "3", "5", "7"), rownames=c("2", "4", "6", "8")) attr(b, "groups") <- factor(rep(c(1,2), each=4)) names(attr(b, "groups")) <- 1:8 class(b) <- "BlockedInfinitySparseMatrix" # Output should still be BISM expect_is(b, "BlockedInfinitySparseMatrix") expect_is(sort(b), "BlockedInfinitySparseMatrix") expect_is(sort(b, byCol=TRUE), "BlockedInfinitySparseMatrix") b.rows <- sort(b, byCol=FALSE) b.cols <- sort(b, byCol=TRUE) expect_identical(dim(b.cols), dim(b)) expect_identical(dim(b.rows), dim(b)) expect_identical(as.matrix(b.cols), as.matrix(b)) expect_identical(as.matrix(b.rows), as.matrix(b)) expect_identical(as.matrix(b), as.matrix(sort(b, decreasing=TRUE))) # When sorting by column, then when looking at column/row it should be # true. coordrc.sortcols <- as.numeric(paste(attr(b.cols, "rows"), attr(b.cols, "cols"), sep="")) coordcr.sortcols <- as.numeric(paste(attr(b.cols, "cols"), attr(b.cols, "rows"), sep="")) expect_true(is.unsorted(coordrc.sortcols)) expect_true(!is.unsorted(coordcr.sortcols)) # Ditto when sorting by row & looking at row first. coordrc.sortrows <- as.numeric(paste(attr(b.rows, "rows"), attr(b.rows, "cols"), sep="")) coordcr.sortrows <- as.numeric(paste(attr(b.rows, "cols"), attr(b.rows, "rows"), sep="")) expect_true(!is.unsorted(coordrc.sortrows)) expect_true(is.unsorted(coordcr.sortrows)) # Checking for bad input on byCol expect_silent(sort(b, byCol=1)) expect_error(sort(b, byCol="a")) expect_error(sort(b, byCol=c(1,1))) data(nuclearplants) m <- match_on(pr ~ cost, data=nuclearplants, within=exactMatch(pr ~ ct, data=nuclearplants)) m.rows <- sort(m, byCol=FALSE) m.cols <- sort(m, byCol=TRUE) # by default, ISM's are row dominant, so resorting by row should not # have any impact. expect_identical(m, m.rows) # However, sorting by column should change the internals, but not # externals. expect_identical(as.matrix(m), as.matrix(m.cols)) expect_false(identical(m, m.cols)) # Double-sorting expect_identical(m, sort(m.cols)) }) test_that("rbinds involving BISMs", { dat <- data.frame(Z=rep(c(0,1,1), 2), B=rep(0:1, each=3), S= 1:6, T= 5:0) bismA <- exactMatch(Z ~B, data=dat[c(1:2, 4:5), ]) bismA <- match_on(Z~S, within=bismA, data=dat[c(1:2, 4:5), ]) bismB <- exactMatch(Z ~B, data=dat[c(1,3,4,6), ]) bismB <- match_on(Z~T, within =bismB, data=dat[c(1,3,4,6), ]) expect_is(bismA, "BlockedInfinitySparseMatrix") expect_is(bismB, "BlockedInfinitySparseMatrix") expect_is(rbind(bismA, bismB), "InfinitySparseMatrix") expect_is(t(bismA), "BlockedInfinitySparseMatrix") expect_is(t(bismB), "BlockedInfinitySparseMatrix") expect_is(cbind(t(bismA), t(bismB)), "InfinitySparseMatrix") expect_true(all(rownames(rbind(bismA, bismB)) %in% c(2, 3, 5, 6))) expect_true(all(colnames(cbind(t(bismA),t(bismB))) %in% c(2, 3, 5, 6))) }) test_that("ISM indexing", { data(nuclearplants) m <- match_on(pr ~ cost, data = nuclearplants, caliper = 1) # [X, X] expect_equal(dim(m[1:3,2:3]), c(3,2)) expect_equal(dim(m[3:2,4:2]), c(2,3)) expect_equal(dim(m[c("A", "C"), c(4,7,1,2:4)]), c(2, 5)) # [X] expect_equal(length(m[1:3]), 3) expect_equal(length(m[c("A", "a")]), 2) # [X,] or [,X] expect_equal(dim(m[1:3, ]), c(3, 22)) expect_equal(dim(m[, 5:3]), c(10, 3)) # [] expect_equal(m, m[]) # [,] m2 <- m[,] m@call <- NULL m2@call <- NULL expect_equal(m, m2) # Strings expect_equal(dim(m["A", "W"]), c(1,1)) expect_equal(dim(m[c("A", "B"), "W"]), c(2,1)) # Logical expect_equal(dim(m[rep(c(TRUE, FALSE), times = 5), ]), c(5, 22)) # Negative indices expect_equal(dim(m[-1, -1]), dim(m) - 1) expect_equal(dim(m[-c(1,3,5),]), dim(m) - c(3,0)) # Error on mixture of signs expect_error(m[c(-1,2)], "mix") # Warning whenever `drop` is presented. expect_warning(m[1:3, 1:3, drop = TRUE]) expect_warning(m[1:3, 1:3, drop = FALSE]) expect_warning(m[1:3,, drop = FALSE]) expect_warning(m[1:3, drop = FALSE]) # Ignoring drop expect_warning({ expect_equal(m[1:3, 2:3, drop = TRUE ], m[1:3, 2:3]) expect_equal(m[1:3, 2:3, drop = FALSE], m[1:3, 2:3]) expect_equal(m[1:3, , drop = TRUE ], m[1:3, ]) expect_equal(m[1:3, , drop = FALSE], m[1:3, ]) expect_equal(m[, 1:3, drop = TRUE ], m[, 1:3]) expect_equal(m[, 1:3, drop = FALSE], m[, 1:3]) expect_equal(m[, , drop = TRUE ], m[, ]) expect_equal(m[, , drop = FALSE], m[, ]) expect_equal(m[, drop = TRUE ], m[, ]) expect_equal(m[, drop = FALSE], m[, ]) expect_equal(m[drop = TRUE ], m[]) expect_equal(m[drop = FALSE], m[]) }) }) test_that("BISM indexing", { m <- match_on(pr ~ cost, data = nuclearplants, caliper = 1, within = exactMatch(pr ~ pt, data = nuclearplants)) expect_is(m[1,1], "InfinitySparseMatrix") m2 <- m[5:10, 18:22] expect_is(m2, "InfinitySparseMatrix") expect_equal(dim(m2), c(6,5)) m3 <- m[8:9, 5:6] expect_true(all(is.infinite(m3))) }) test_that("ISM subset replacement", { a <- as.InfinitySparseMatrix(matrix(c(1, Inf, 2, 3, 4, 5), nrow = 3, ncol = 2)) a[2,2] <- 10 expect_equal(as.vector(as.matrix(a)), c(1, Inf, 2, 3, 10, 5)) expect_true(all(as.matrix(a) == c(1, Inf, 2, 3, 10, 5))) a[1,1:2] <- c(20,40) expect_equal(as.vector(as.matrix(a)), c(20, Inf, 2, 40, 10, 5)) a[2,1:2] <- c(-10, -20) expect_equal(as.vector(as.matrix(a)), c(20, -10, 2, 40, -20, 5)) a[2,] <- c(-30, -40) expect_equal(as.vector(as.matrix(a)), c(20, -30, 2, 40, -40, 5)) a[,1] <- c(5,6,7) expect_equal(as.vector(as.matrix(a)), c(5, 6, 7, 40, -40, 5)) a[1:2, 1:2] <- c(1,2,3,4) expect_equal(as.vector(as.matrix(a)), c(1, 2, 7, 3, 4, 5)) a[1:2, 1:2] <- matrix(c(8,7,6,5), nrow = 2) expect_equal(as.vector(as.matrix(a)), c(8, 7, 7, 6, 5, 5)) a[1,1:2] <- c(Inf, Inf) expect_equal(as.vector(as.matrix(a)), c(Inf, 7, 7, Inf, 5, 5)) expect_length(a@.Data, 4) # Logical indexing a[c(TRUE, TRUE, FALSE), c(FALSE, TRUE)] <- 1:2 expect_equal(as.vector(as.matrix(a)), c(Inf, 7, 7, 1, 2, 5)) # Inf replacement a[, 1] <- Inf expect_equal(as.vector(as.matrix(a)), c(Inf, Inf, Inf, 1, 2, 5)) expect_error(a[, 1] <- 1:2, "length") expect_error(a[1:3, 1:2] <- matrix(c(8,7,6,5), nrow = 2), "length") a[,-2] <- 1:3 expect_equal(as.vector(as.matrix(a)), c(1, 2, 3, 1, 2, 5)) a[-c(1,2),] <- c(10, 20) expect_equal(as.vector(as.matrix(a)), c(1, 2, 10, 1, 2, 20)) # String indexing data(nuclearplants) m <- match_on(pr ~ cost, data = nuclearplants, caliper = 1) m["A",] <- Inf expect_true(all(m@rows > 1)) m["A", "H"] <- 10 expect_true(sum(m@rows == 1) == 1) }) test_that("BISM subset replacement", { m <- match_on(pr ~ cost, data = nuclearplants, caliper = 1, within = exactMatch(pr ~ pt, data = nuclearplants)) expect_is(m, "BlockedInfinitySparseMatrix") # Replacing element that is entirely within a group m[1,1] <- 4 expect_is(m, "BlockedInfinitySparseMatrix") m[8:10, 18:19] <- 3 expect_is(m, "InfinitySparseMatrix") expect_false(is(m, "BlockedInfinitySparseMatrix")) expect_true(all(m[8:10, 18:19] == 3)) }) test_that("as.list ISM/BISM", { # BISM m <- match_on(pr ~ cost, data = nuclearplants, caliper = 1, within = exactMatch(pr ~ pt, data = nuclearplants)) expect_is(m, "BlockedInfinitySparseMatrix") m2 <- as.list(m) expect_is(m2, "list") expect_length(m2, 2) expect_true(all(sapply(m2, is, "InfinitySparseMatrix"))) # ISM m <- match_on(pr ~ cost, data = nuclearplants, caliper = 1) expect_is(m, "InfinitySparseMatrix") m2 <- as.list(m) expect_is(m2, "list") expect_length(m2, 1) expect_true(all(sapply(m2, is, "InfinitySparseMatrix"))) # DenseMatrix m <- match_on(pr ~ cost, data = nuclearplants) expect_is(m, "DenseMatrix") m2 <- as.list(m) expect_is(m2, "list") expect_length(m2, 1) expect_true(all(sapply(m2, is, "InfinitySparseMatrix"))) }) test_that("dbind", { data(nuclearplants) np <- nuclearplants # Dense/Dense m1 <- match_on(pr ~ cost, data = np[np$ct == 0, ]) m2 <- match_on(pr ~ cost, data = np[np$ct == 1, ]) bm <- dbind(m1, m2) expect_identical(as.InfinitySparseMatrix(m1), dbind(m1)) expect_true(is(bm, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(bm, is, TRUE, "InfinitySparseMatrix"))) expect_true(all.equal(subdim(bm), data.frame(dim(m1), dim(m2)), check.attributes = FALSE)) expect_identical(as.list(bm)[[1]], as.InfinitySparseMatrix(m1)) expect_identical(as.list(bm)[[2]], as.InfinitySparseMatrix(m2)) # ISM/ISM im1 <- match_on(pr ~ cost, data = np[np$ct == 0, ], caliper = 1) im2 <- match_on(pr ~ cost, data = np[np$ct == 1, ], caliper = 1) bim <- dbind(im1, im2) expect_identical(im1, dbind(im1)) expect_true(is(bim, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(bim, is, TRUE, "InfinitySparseMatrix"))) expect_true(all.equal(subdim(bim), data.frame(dim(im1), dim(im2)), check.attributes = FALSE)) im1@call <- NULL im2@call <- NULL expect_identical(as.list(bim)[[1]], im1) expect_identical(as.list(bim)[[2]], im2) # Dense/ISM b2m <- dbind(m1, im2) expect_true(is(b2m, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(b2m, is, TRUE, "InfinitySparseMatrix"))) expect_true(all.equal(subdim(b2m), data.frame(dim(m1), dim(im2)), check.attributes = FALSE)) expect_identical(as.list(b2m)[[1]], as.InfinitySparseMatrix(m1)) expect_identical(as.list(b2m)[[2]], im2) #BISM/Dense np$group <- as.numeric(cut(np$cap, breaks = c(0, 750, 900, 2000))) b1 <- match_on(pr ~ cost + strata(group), data = np[np$group < 3, ]) m3 <- match_on(pr ~ cost, data = np[np$group == 3,]) bbm <- dbind(b1, m3) expect_identical(b1, dbind(b1)) expect_true(is(bbm, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(bbm, is, TRUE, "InfinitySparseMatrix"))) expect_length(unique(bbm@groups), 3) expect_true(all.equal(subdim(bbm), data.frame(subdim(b1), dim(m3)), check.attributes = FALSE)) # BISM/ISM im3 <- match_on(pr ~ cost, data = np[np$group == 3,], caliper = 1) bibm <- dbind(b1, im3) expect_true(is(bibm, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(bibm, is, TRUE, "InfinitySparseMatrix"))) expect_length(unique(bibm@groups), 3) expect_true(all.equal(subdim(bibm), data.frame(subdim(b1), dim(im3)), check.attributes = FALSE)) # BISM/BISM np$group <- as.numeric(cut(np$cap, breaks = c(0, 600, 825, 1000, 2000))) b1 <- match_on(pr ~ cost + strata(group), data = np[np$group < 3,]) b2 <- match_on(pr ~ cost + strata(group), data = np[np$group >= 3,]) b2bm <- dbind(b1, b2) expect_true(is(b2bm, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(b2bm, is, TRUE, "InfinitySparseMatrix"))) expect_length(unique(b2bm@groups), 4) expect_true(all.equal(subdim(b2bm), data.frame(subdim(b1), subdim(b2)), check.attributes = FALSE)) # >2 elements m1 <- match_on(pr ~ cost, data = np[np$group == 1,]) m2 <- match_on(pr ~ cost, data = np[np$group == 2,]) m3 <- match_on(pr ~ cost, data = np[np$group == 3,]) m4 <- match_on(pr ~ cost, data = np[np$group == 4,]) b4bm <- dbind(m4, m2, m3, m1) expect_true(is(b4bm, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(b4bm, is, TRUE, "InfinitySparseMatrix"))) expect_length(unique(b4bm@groups), 4) expect_true(all.equal(subdim(b4bm), data.frame(dim(m4), dim(m2), dim(m3), dim(m1)), check.attributes = FALSE)) # errors and warnings expect_error(dbind(m1, 1), "Cannot convert") # same names expect_warning(bdupm <- dbind(m1, b1), "Duplicated column or row names") expect_true(is(bdupm, "BlockedInfinitySparseMatrix")) expect_true(all(vapply(bdupm, is, TRUE, "InfinitySparseMatrix"))) expect_length(unique(bdupm@groups), 3) expect_true(all.equal(subdim(bdupm), data.frame(dim(m1), subdim(b1)), check.attributes = FALSE)) expect_error(dbind(m1, b1, force_unique_names = TRUE), "Duplicated column or row names") # passing a list b4bml <- dbind(list(m4, m2, m3, m1)) expect_identical(b4bml, b4bm) b4bml2 <- dbind(list(m4, m2), list(m3, m1)) expect_identical(b4bml2, b4bm) b4bml3 <- dbind(list(m4, m2), m3, list(m1)) expect_identical(b4bml3, b4bm) bmix1 <- dbind(b1, m3, m4) bmix2 <- dbind(list(b1, m3, m4)) bmix3 <- dbind(list(b1, m3), m4) expect_identical(bmix1, bmix2) expect_identical(bmix1, bmix3) }) test_that("dbind'ing a very large number of matrices", { data(nuclearplants) m1 <- match_on(pr ~ cost, data = nuclearplants[nuclearplants$pt == 1, ]) expect_warning(dm1 <- dbind(lapply(1:26, function(x) m1)), "Duplicated") expect_true(all(grepl("^[a-z]\\.[a-f]$",dm1@colnames))) expect_warning(dm2 <- dbind(lapply(1:27, function(x) m1)), "Duplicated") expect_identical(dm1@colnames, dm2@colnames[seq_along(dm1@colnames)]) expect_true(all(grepl("^aa\\.[a-f]$", dm2@colnames[-seq_along(dm1@colnames)]))) expect_warning(dm3 <- dbind(lapply(1:500, function(x) m1)), "Duplicated") expect_true(all(grepl("^[a-z]{2}\\.[a-f]$", dm3@colnames[-seq_along(dm1@colnames)]))) expect_warning(dm4 <- dbind(lapply(1:1000, function(x) m1)), "Duplicated") expect_identical(dm3@colnames, dm4@colnames[seq_along(dm3@colnames)]) expect_true(all(grepl("^[a-z]{3}\\.[a-f]$", tail(dm4@colnames, 100)))) }) test_that("as ism or bism", { m1 <- match_on(pr ~ cost, data = nuclearplants) expect_is(m1, "DenseMatrix") expect_is(.as.ism_or_bism(m1), "InfinitySparseMatrix") m2 <- as.matrix(m1) expect_is(m2, "matrix") expect_is(.as.ism_or_bism(m2), "InfinitySparseMatrix") m3 <- match_on(pr ~ cost, data = nuclearplants, caliper = 1) expect_is(m3, "InfinitySparseMatrix") expect_is(.as.ism_or_bism(m3), "InfinitySparseMatrix") m4 <- match_on(pr ~ cost + strata(pt), data = nuclearplants) expect_is(m4, "BlockedInfinitySparseMatrix") expect_is(.as.ism_or_bism(m4), "BlockedInfinitySparseMatrix") expect_error(.as.ism_or_bism(1), "Cannot convert") expect_error(.as.ism_or_bism(data.frame(1:4)), "Cannot convert") expect_error(.as.ism_or_bism(list(1, 2)), "Cannot convert") })