File: array_selection.Rd

package info (click to toggle)
r-bioc-s4arrays 1.6.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 476 kB
  • sloc: ansic: 730; makefile: 2
file content (268 lines) | stat: -rw-r--r-- 9,642 bytes parent folder | download
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
\name{array selection}

\alias{array selection}
\alias{array_selection}
\alias{array selections}
\alias{array_selections}
\alias{L-index}
\alias{Lindex}
\alias{M-index}
\alias{Mindex}
\alias{N-index}
\alias{Nindex}

\alias{Lindex2Mindex}
\alias{Mindex2Lindex}

\title{Manipulation of array selections}

\description{
  NOTE: The tools documented in this man page are primarily intended
  for developers or advanced users curious about the internals of the
  \pkg{SparseArray} or \pkg{DelayedArray} packages. End users typically
  don't need them for their regular use of \link[SparseArray]{SparseArray}
  or \link[DelayedArray]{DelayedArray} objects.

  An \emph{array selection} is just an index into an array-like object that
  contains the information of which array elements are selected. This index
  can take various forms but 3 special forms are particularly useful and
  extensively used in the context of the \pkg{SparseArray} and
  \pkg{DelayedArray} packages:
  \emph{linear index} (also referred to as \emph{L-index} or \emph{Lindex}),
  \emph{matrix index} (also referred to as \emph{M-index} or \emph{Mindex}),
  \emph{N-dimensional index} (also referred to as \emph{N-index} or
  \emph{Nindex}). See Details section below for more information.

  Two utility functions are provided at the moment to convert back and forth
  between \emph{L-indices} and \emph{M-indices}. More will be added in the
  future to convert between other types of array indices.
}

\usage{
## Convert back and forth between L-indices and M-indices:
Lindex2Mindex(Lindex, dim, use.names=FALSE)
Mindex2Lindex(Mindex, dim, use.names=FALSE, as.integer=FALSE)
}

\arguments{
  \item{Lindex}{
    An \emph{L-index}. See Details section below.
  }
  \item{Mindex}{
    An \emph{M-index}. See Details section below.

    For convenience, \code{Mindex} can also be specified as an integer vector
    with one element per dimension in the underlying array, in which case it
    will be treated like a 1-row matrix.
  }
  \item{dim}{
    An integer vector containing the dimensions of the underlying array.

    Note that \code{dim} can also be an integer matrix, in which case
    it must have one row per element in \code{Lindex} (or per row in
    \code{Mindex}) and one column per dimension in the underlying array.
  }
  \item{use.names}{
    Should the names (or rownames) on the input be propagated to the output?
  }
  \item{as.integer}{
    Set to \code{TRUE} to force \code{Mindex2Lindex} to return the L-index
    as an integer vector. Dangerous!

    By default, i.e. when \code{as.integer=FALSE}, \code{Mindex2Lindex} will
    return the L-index either as an integer or numeric vector. It will choose
    the former only if it's safe, that is, only if all the values in the
    L-index "fit" in the integer type. More precisely:
    \itemize{
      \item If \code{dim} is not a matrix (i.e. is a vector) or if it's a
            matrix with a single row: \code{Mindex2Lindex} returns an integer
            or numeric vector depending on whether \code{prod(dim)} is <=
            \code{.Machine$integer.max} (2^31 - 1) or not.
      \item Otherwise \code{Mindex2Lindex} returns a numeric vector.
    }
    Note that with these rules, \code{Mindex2Lindex} can return a numeric
    vector even if an integer vector could have been used.

    Use \code{as.integer=TRUE} only in situations where you know that all
    the L-index values are going to "fit" in the integer type.
    \code{Mindex2Lindex} will return garbage if they don't.
  }
}

\details{
  The 3 special forms of array indices that are extensively used in the
  context of the \pkg{SparseArray} and \pkg{DelayedArray} packages:

  \enumerate{
    \item \emph{Linear index} (or \emph{L-index} or \emph{Lindex}):
          A numeric vector where each value is >= 1 and <= the length
          of the array-like object. When using an L-index to subset an
          array-like object, the returned value is a vector-like object
          (i.e. no dimensions) of the same length as the L-index.

          Example:
          \preformatted{
            a <- array(101:124, 4:2)
            Lindex <- c(7, 2, 24, 2)
            a[Lindex]
          }

    \item \emph{Matrix index} (or \emph{M-index} or \emph{Mindex}):
          An integer matrix with one column per dimension in the array-like
          object and one row per array element in the selection.
          The values in each column must be >= 1 and <= the extent
          of the array-like object along the corresponding dimension.
          When using an M-index to subset an array-like object, the returned
          value is a vector-like object (i.e. no dimensions) of length the
          number of rows in the M-index.

          Example:
          \preformatted{
            a <- array(101:124, 4:2)
            Mindex <- rbind(c(3, 2, 1),
                            c(2, 1, 1),
                            c(4, 3, 2),
                            c(2, 1, 1))
            a[Mindex]
          }

          Note that this is the type of index returned by
          \code{base::\link[base]{arrayInd}}.

    \item \emph{N-dimensional} (or \emph{N-index} or \emph{Nindex}):
          A list with one list element per dimension in the array-like object.
          Each list element must be a subscript describing the selection along
          the corresponding dimension of the array-like object.
          IMPORTANT: A \code{NULL} subscript is interpreted as a \emph{missing}
          subscript ("missing" like in \code{a[ , , 1:2]}), that is, as a
          subscript that runs along the full extend of the corresponding
          dimension of the array-like object. This means that before an
          N-index can be used in a call to \code{[}, \code{[<-}, \code{[[}
          or \code{[[<-}, the \code{NULL} list elements in it must be
          replaced with objects of class \code{"name"}.
          When using an N-index to subset an array-like object, the returned
          value is another array-like object of dimensions the lengths of the
          selections along each dimensions.

          Examples:
          \preformatted{
            a <- array(101:124, 4:2)

            ## Normalized N-index (i.e. non-NULL subscripts are integer
            ## vectors with positive values only):

            Nindex <- list(c(1, 4, 1), NULL, 1)
            ## Same as a[c(1, 4, 1), , 1, drop=FALSE]:
            S4Arrays:::subset_by_Nindex(a, Nindex)

            Nindex <- list(integer(0), NULL, 1)
            ## Same as a[integer(0), , 1, drop=FALSE]:
            S4Arrays:::subset_by_Nindex(a, Nindex)

            ## Non-normalized N-index:

            Nindex <- list(-3, NULL, c(TRUE, FALSE, FALSE))
            Nindex <- S4Arrays:::normalize_Nindex(Nindex, a)
            ## Same as a[-3, , 1, drop=FALSE]:
            S4Arrays:::subset_by_Nindex(a, Nindex)

            Nindex <- list(IRanges(2, 4), NULL, 1)
            Nindex <- S4Arrays:::normalize_Nindex(Nindex, a)
            ## Same as a[2:4, , 1, drop=FALSE]:
            S4Arrays:::subset_by_Nindex(a, Nindex)

            dimnames(a)[[1]] <- LETTERS[1:4]
            Nindex <- list(c("D", "B"), NULL, 1)
            Nindex <- S4Arrays:::normalize_Nindex(Nindex, a)
            ## Same as a[c("D", "B"), , 1, drop=FALSE]:
            S4Arrays:::subset_by_Nindex(a, Nindex)
          }
  }
}

\value{
  \code{Lindex2Mindex} returns an M-index.

  \code{Mindex2Lindex} returns an L-index.
}

\seealso{
  \code{\link[base]{arrayInd}} in the \pkg{base} package.
}

\examples{
## ---------------------------------------------------------------------
## M-index vs L-index
## ---------------------------------------------------------------------

a <- array(101:124, 4:2)

## The same "array selection" can be represented by an M-index or
## an L-index. Here we use both representations to select the same
## 4 array elements:
Mindex <- rbind(c(3, 2, 1),
                c(2, 1, 1),
                c(4, 3, 2),
                c(2, 1, 1))
a[Mindex]

Lindex <- c(7, 2, 24, 2)
a[Lindex]

## Sanity check:
stopifnot(identical(a[Mindex], a[Lindex]))

## ---------------------------------------------------------------------
## Convert back and forth between M-index and L-index representation
## ---------------------------------------------------------------------

Mindex2Lindex(Mindex, dim(a))  # L-index

Lindex2Mindex(Lindex, dim(a))  # M-index

## Sanity checks:
storage.mode(Mindex) <- storage.mode(Lindex) <- "integer"
stopifnot(identical(Mindex2Lindex(Mindex, dim(a)), Lindex))
stopifnot(identical(Lindex2Mindex(Lindex, dim(a)), Mindex))

## ---------------------------------------------------------------------
## More Mindex2Lindex() examples
## ---------------------------------------------------------------------

dim <- 4:2
Mindex2Lindex(c(4, 3, 1), dim)
Mindex2Lindex(c(4, 3, 2), dim)

Mindex <- rbind(c(1, 1, 1),
                c(2, 1, 1),
                c(3, 1, 1),
                c(4, 1, 1),
                c(1, 2, 1),
                c(1, 1, 2),
                c(4, 3, 2))

Mindex2Lindex(Mindex, dim)

## With a matrix of dimensions:

dims <- rbind(c(4L, 3L),
              c(5L, 3L),
              c(6L, 3L))

Mindex <- rbind(c(1,  2),
                c(1,  2),
                c(1,  2))

Mindex2Lindex(Mindex, dims)

## Sanity checks:

dim <- c(33:30, 45L, 30L)
stopifnot(Mindex2Lindex(rep(1, 6), dim) == 1)
stopifnot(Mindex2Lindex(dim, dim) == prod(dim))

stopifnot(identical(Mindex2Lindex(arrayInd(1:120, 6:4), 6:4), 1:120))
stopifnot(identical(Mindex2Lindex(arrayInd(840:1, 4:7), 4:7), 840:1))
}
\keyword{array}
\keyword{utilities}