/
listenv,dims.R
125 lines (109 loc) · 2.73 KB
/
listenv,dims.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#' @export
dim.listenv <- function(x) attr(x, "dim.", exact = TRUE)
#' @export
`dim<-.listenv` <- function(x, value) {
n <- length(x)
if (!is.null(value)) {
names <- names(value)
value <- as.integer(value)
p <- prod(as.double(value))
if (p != n) {
if (n == 0) {
length(x) <- p
} else {
stopf("Cannot set dimension to c(%s) because its length do not match the length of the object: %d != %s", paste(value, collapse = ", "), p, n)
}
}
names(value) <- names
}
## Always remove "dimnames" and "names" attributes, cf. help("dim")
dimnames(x) <- NULL
names(x) <- NULL
attr(x, "dim.") <- value
x
}
#' Set the dimension of an object
#'
#' @param x An \R object, e.g. a list environment, a matrix, an array, or
#' a data frame.
#'
#' @param value A numeric vector coerced to integers.
#' If one of the elements is missing, then its value is inferred from the
#' other elements (which must be non-missing) and the length of `x`.
#'
#' @return An object with the dimensions set, similar to what
#' \code{\link[base:dim]{dim(x) <- value}} returns.
#'
#' @examples
#' x <- 1:6
#' dim_na(x) <- c(2, NA)
#' print(dim(x)) ## [1] 2 3
#'
#' @name dim_na
#' @aliases dim_na<-
#' @export
`dim_na<-` <- function(x, value) {
if (!is.null(value)) {
value <- as.integer(value)
nas <- which(is.na(value))
if (length(nas) > 0) {
if (length(nas) > 1) {
stopf("Argument 'value' may only have one NA: %s",
sprintf("c(%s)", paste(value, collapse = ", ")))
}
value[nas] <- as.integer(length(x) / prod(value[-nas]))
}
}
dim(x) <- value
invisible(x)
}
#' @export
dimnames.listenv <- function(x) attr(x, "dimnames.", exact = TRUE)
#' @export
`dimnames<-.listenv` <- function(x, value) {
dim <- dim(x)
if (is.null(dim) && !is.null(value)) {
stop("'dimnames' applied to non-array")
}
for (kk in seq_along(dim)) {
names <- value[[kk]]
if (is.null(names)) next
n <- length(names)
if (n != dim[kk]) {
stopf("Length of 'dimnames' for dimension #%d not equal to array extent: %d != %d", kk, n, dim[kk])
}
}
attr(x, "dimnames.") <- value
x
}
#' @method is.matrix listenv
#' @export
is.matrix.listenv <- function(x, ...) {
dim <- dim(x)
(length(dim) == 2L)
}
#' @export
is.array.listenv <- function(x, ...) {
dim <- dim(x)
!is.null(dim)
}
#' @method as.vector listenv
#' @export
as.vector.listenv <- function(x, mode = "any") {
if (mode == "any") mode <- "list"
x <- as.list(x)
if (mode != "list") {
x <- as.vector(x, mode = mode)
}
x
}
#' @export
#' @method as.matrix listenv
as.matrix.listenv <- function(x, ...) {
dim <- dim(x)
if (length(dim) != 2L) {
dim <- c(length(x), 1L)
dim(x) <- dim
}
x
}