Skip to content

Commit

Permalink
Add cbind and rbind methods
Browse files Browse the repository at this point in the history
Fixes #311
  • Loading branch information
jranke committed Aug 12, 2024
1 parent 123c23d commit e868eb7
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 0 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ S3method(as_units,units)
S3method(boxplot,units)
S3method(c,mixed_units)
S3method(c,units)
S3method(cbind,units)
S3method(diff,units)
S3method(drop_units,data.frame)
S3method(drop_units,mixed_units)
Expand All @@ -55,6 +56,7 @@ S3method(plot,units)
S3method(print,mixed_units)
S3method(print,units)
S3method(quantile,units)
S3method(rbind,units)
S3method(rep,units)
S3method(seq,units)
S3method(set_units,logical)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# version devel

* Add methods for `cbind` and `rbind`; fixes #311

* Performance improvements in `data.frame` methods; suggested in #361 @grcatlin

* Fix `weighted.mean.units` for unitless objects; #363
Expand Down
46 changes: 46 additions & 0 deletions R/misc.R
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,49 @@ unique.units <- function(x, incomparables = FALSE, ...) {
NextMethod() else unique.array(x, incomparables, ...)
.as.units(xx, units(x))
}

#' Combine R Objects by Rows or Columns
#'
#' S3 methods for \code{units} objects (see \code{\link[base]{cbind}}).
#'
#' @inheritParams base::cbind
#' @name cbind.units
#'
#' @examples
#' x <- set_units(1, m/s)
#' y <- set_units(1:3, m/s)
#' z <- set_units(8:10, m/s)
#' (m <- cbind(x, y)) # the '1' (= shorter vector) is recycled
#' (m <- cbind(m, z)[, c(1, 3, 2)]) # insert a column
#' (m <- rbind(m, z)) # insert a row
#' @export
cbind.units <- function(..., deparse.level = 1) {
dots <- list(...)
stopifnot(all(sapply(dots, inherits, "units")))
u <- units(dots[[1]])
dots <- lapply(dots, function(x) {
d <- dim(x)
dn <- dimnames(x)
dots_unified <- set_units(x, u, mode = "standard")
ret <- as.numeric(dots_unified)
dim(ret) <- d
if (!is.null(dn)) dimnames(ret) <- dn
return(ret)
})

nm <- names(as.list(match.call()))
nm <- nm[nm != "" & nm != "deparse.level"]
if (is.null(nm))
names(dots) <- sapply(substitute(list(...))[-1], deparse)
else names(dots) <- nm

call <- as.character(match.call()[[1]])
value <- do.call(call, c(dots, deparse.level=deparse.level))
attr(value, "units") <- u
class(value) <- "units"
return(value)
}

#' @rdname cbind.units
#' @export
rbind.units <- cbind.units
37 changes: 37 additions & 0 deletions man/cbind.units.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions tests/testthat/test_misc.R
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,35 @@ test_that("duplicated-related methods work as expected", {
expect_equal(anyDuplicated(x), anyDuplicated(drop_units(x)))
expect_equal(unique(x), x[1, , drop=FALSE])
})

test_that("bind methods work properly", {
a <- set_units(1:10, m)
b <- set_units((1:10) * 0.001, km)

x <- rbind(x=a, y=a)
y <- rbind(x=a, y=b)
expect_equal(as.numeric(x), as.numeric(y))
expect_equal(rownames(x), c("x", "y"))
expect_equal(rownames(y), c("x", "y"))
x <- rbind(rbind(a, a), a)
y <- rbind(b, rbind(b, b))
expect_equal(as.numeric(x), as.numeric(y) * 1000)
expect_equal(rownames(x), c("a", "a", "a"))
expect_equal(rownames(y), c("b", "b", "b"))

x <- cbind(x=a, y=a)
y <- cbind(x=a, y=b)
expect_equal(as.numeric(x), as.numeric(y))
expect_equal(colnames(x), c("x", "y"))
expect_equal(colnames(y), c("x", "y"))
x <- cbind(cbind(a, a), a)
y <- cbind(b, cbind(b, b))
expect_equal(as.numeric(x), as.numeric(y) * 1000)
expect_equal(colnames(x), c("a", "a", "a"))
expect_equal(colnames(y), c("b", "b", "b"))

z <- cbind(
rbind(a, b),
rbind(x = a, y = b))
expect_equal(dimnames(z), list(c("a", "b"), NULL))
})

0 comments on commit e868eb7

Please sign in to comment.