I suspect this will have suboptimal performance since the TRUEs will get recycled. (Maybe there is, or could be, ALTREP, support for recycling) Hadley On Fri, Jun 8, 2018 at 10:16 AM, Berry, Charles <ccberry at ucsd.edu> wrote:> > >> On Jun 8, 2018, at 8:45 AM, Hadley Wickham <h.wickham at gmail.com> wrote: >> >> Hi all, >> >> Is there a better to way to subset the ROWs (in the sense of NROW) of >> an vector, matrix, data frame or array than this? > > > You can use TRUE to fill the subscripts for dimensions 2:nd > >> >> subset_ROW <- function(x, i) { >> nd <- length(dim(x)) >> if (nd <= 1L) { >> x[i] >> } else { >> dims <- rep(list(quote(expr = )), nd - 1L) >> do.call(`[`, c(list(quote(x), quote(i)), dims, list(drop = FALSE))) >> } >> } > > > subset_ROW <- > function(x,i) > { > mc <- quote(x[i]) > nd <- max(1L, length(dim(x))) > mc[seq(4, length=nd-1L)] <- rep(list(TRUE), nd - 1L) > mc[["drop"]] <- FALSE > eval(mc) > > } > >> >> subset_ROW(1:10, 4:6) >> #> [1] 4 5 6 >> >> str(subset_ROW(array(1:10, c(10)), 2:4)) >> #> int [1:3(1d)] 2 3 4 >> str(subset_ROW(array(1:10, c(10, 1)), 2:4)) >> #> int [1:3, 1] 2 3 4 >> str(subset_ROW(array(1:10, c(5, 2)), 2:4)) >> #> int [1:3, 1:2] 2 3 4 7 8 9 >> str(subset_ROW(array(1:10, c(10, 1, 1)), 2:4)) >> #> int [1:3, 1, 1] 2 3 4 >> >> subset_ROW(data.frame(x = 1:10, y = 10:1), 2:4) >> #> x y >> #> 2 2 9 >> #> 3 3 8 >> #> 4 4 7 >> > > HTH, > > Chuck >-- http://hadley.nz
Also the TRUEs cause problems if some dimensions are 0: > matrix(raw(0), nrow=5, ncol=0)[1:3 , TRUE] Error in matrix(raw(0), nrow = 5, ncol = 0)[1:3, TRUE] : (subscript) logical subscript too long H. On 06/08/2018 10:29 AM, Hadley Wickham wrote:> I suspect this will have suboptimal performance since the TRUEs will > get recycled. (Maybe there is, or could be, ALTREP, support for > recycling) > Hadley > > On Fri, Jun 8, 2018 at 10:16 AM, Berry, Charles <ccberry at ucsd.edu> wrote: >> >> >>> On Jun 8, 2018, at 8:45 AM, Hadley Wickham <h.wickham at gmail.com> wrote: >>> >>> Hi all, >>> >>> Is there a better to way to subset the ROWs (in the sense of NROW) of >>> an vector, matrix, data frame or array than this? >> >> >> You can use TRUE to fill the subscripts for dimensions 2:nd >> >>> >>> subset_ROW <- function(x, i) { >>> nd <- length(dim(x)) >>> if (nd <= 1L) { >>> x[i] >>> } else { >>> dims <- rep(list(quote(expr = )), nd - 1L) >>> do.call(`[`, c(list(quote(x), quote(i)), dims, list(drop = FALSE))) >>> } >>> } >> >> >> subset_ROW <- >> function(x,i) >> { >> mc <- quote(x[i]) >> nd <- max(1L, length(dim(x))) >> mc[seq(4, length=nd-1L)] <- rep(list(TRUE), nd - 1L) >> mc[["drop"]] <- FALSE >> eval(mc) >> >> } >> >>> >>> subset_ROW(1:10, 4:6) >>> #> [1] 4 5 6 >>> >>> str(subset_ROW(array(1:10, c(10)), 2:4)) >>> #> int [1:3(1d)] 2 3 4 >>> str(subset_ROW(array(1:10, c(10, 1)), 2:4)) >>> #> int [1:3, 1] 2 3 4 >>> str(subset_ROW(array(1:10, c(5, 2)), 2:4)) >>> #> int [1:3, 1:2] 2 3 4 7 8 9 >>> str(subset_ROW(array(1:10, c(10, 1, 1)), 2:4)) >>> #> int [1:3, 1, 1] 2 3 4 >>> >>> subset_ROW(data.frame(x = 1:10, y = 10:1), 2:4) >>> #> x y >>> #> 2 2 9 >>> #> 3 3 8 >>> #> 4 4 7 >>> >> >> HTH, >> >> Chuck >> > > >-- Herv? Pag?s Program in Computational Biology Division of Public Health Sciences Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N, M1-B514 P.O. Box 19024 Seattle, WA 98109-1024 E-mail: hpages at fredhutch.org Phone: (206) 667-5791 Fax: (206) 667-1319
> On Jun 8, 2018, at 10:37 AM, Herv? Pag?s <hpages at fredhutch.org> wrote: > > Also the TRUEs cause problems if some dimensions are 0: > > > matrix(raw(0), nrow=5, ncol=0)[1:3 , TRUE] > Error in matrix(raw(0), nrow = 5, ncol = 0)[1:3, TRUE] : > (subscript) logical subscript too longOK. But this is easy enough to handle.> > H. > > On 06/08/2018 10:29 AM, Hadley Wickham wrote: >> I suspect this will have suboptimal performance since the TRUEs will >> get recycled. (Maybe there is, or could be, ALTREP, support for >> recycling) >> HadleyAFAICS, it is not an issue. Taking arr <- array(rnorm(2^22),c(2^10,4,4,4)) as a test case and using a function that will either use the literal code `x[i,,,,drop=FALSE]' or `eval(mc)': subset_ROW4 <- function(x, i, useLiteral=FALSE) { literal <- quote(x[i,,,,drop=FALSE]) mc <- quote(x[i]) nd <- max(1L, length(dim(x))) mc[seq(4,length=nd-1L)] <- rep(TRUE, nd-1L) mc[["drop"]] <- FALSE if (useLiteral) eval(literal) else eval(mc) } I get identical times with system.time(for (i in 1:10000) subset_ROW4(arr,seq(1,length=10,by=100),TRUE)) and with system.time(for (i in 1:10000) subset_ROW4(arr,seq(1,length=10,by=100),FALSE)) Changing the dimensions to c(2^5, 2^7, 4, 4 ) and running something similar also shows equal times. Chuck>> On Fri, Jun 8, 2018 at 10:16 AM, Berry, Charles <ccberry at ucsd.edu> wrote: >>> >>> >>>> On Jun 8, 2018, at 8:45 AM, Hadley Wickham <h.wickham at gmail.com> wrote: >>>> >>>> Hi all, >>>> >>>> Is there a better to way to subset the ROWs (in the sense of NROW) of >>>> an vector, matrix, data frame or array than this? >>> >>> >>> You can use TRUE to fill the subscripts for dimensions 2:nd >>> >>>> >>>> subset_ROW <- function(x, i) { >>>> nd <- length(dim(x)) >>>> if (nd <= 1L) { >>>> x[i] >>>> } else { >>>> dims <- rep(list(quote(expr = )), nd - 1L) >>>> do.call(`[`, c(list(quote(x), quote(i)), dims, list(drop = FALSE))) >>>> } >>>> } >>> >>> >>> subset_ROW <- >>> function(x,i) >>> { >>> mc <- quote(x[i]) >>> nd <- max(1L, length(dim(x))) >>> mc[seq(4, length=nd-1L)] <- rep(list(TRUE), nd - 1L) >>> mc[["drop"]] <- FALSE >>> eval(mc) >>> >>> } >>> >>>> >>>> subset_ROW(1:10, 4:6) >>>> #> [1] 4 5 6 >>>> >>>> str(subset_ROW(array(1:10, c(10)), 2:4)) >>>> #> int [1:3(1d)] 2 3 4 >>>> str(subset_ROW(array(1:10, c(10, 1)), 2:4)) >>>> #> int [1:3, 1] 2 3 4 >>>> str(subset_ROW(array(1:10, c(5, 2)), 2:4)) >>>> #> int [1:3, 1:2] 2 3 4 7 8 9 >>>> str(subset_ROW(array(1:10, c(10, 1, 1)), 2:4)) >>>> #> int [1:3, 1, 1] 2 3 4 >>>> >>>> subset_ROW(data.frame(x = 1:10, y = 10:1), 2:4) >>>> #> x y >>>> #> 2 2 9 >>>> #> 3 3 8 >>>> #> 4 4 7 >>>> >>> >>> HTH, >>> >>> Chuck >>> > > -- > Herv? Pag?s > > Program in Computational Biology > Division of Public Health Sciences > Fred Hutchinson Cancer Research Center > 1100 Fairview Ave. N, M1-B514 > P.O. Box 19024 > Seattle, WA 98109-1024 > > E-mail: hpages at fredhutch.org > Phone: (206) 667-5791 > Fax: (206) 667-1319