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?
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(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
It seems like there should be a way to do this that doesn't require
generating a call with missing arguments, but I can't think of it.
Thanks!
Hadley
--
http://hadley.nz
El vie., 8 jun. 2018 a las 17:46, Hadley Wickham (<h.wickham at gmail.com>) escribi?:> > 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? > > 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(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 > > It seems like there should be a way to do this that doesn't require > generating a call with missing arguments, but I can't think of it.The following code seems to work. The only minor drawback is that, for the last case, the output is not a data frame. subset_ROW <- function(x, i) { nd <- length(dim(x)) if (nd <= 1L) return(x[i]) xx <- apply(x, 2:nd, `[`, i, drop=FALSE) dim(xx) <- c(length(i), dim(x)[-1]) xx } I?aki> > Thanks! > > Hadley > > -- > http://hadley.nz >
Sorry, without remnants from other attempts:
subset_ROW <- function(x, i) {
nd <- length(dim(x))
if (nd <= 1L)
return(x[i])
apply(x, 2:nd, `[`, i, drop=FALSE)
}
El vie., 8 jun. 2018 a las 19:07, I?aki ?car (<i.ucar86 at gmail.com>)
escribi?:>
> El vie., 8 jun. 2018 a las 17:46, Hadley Wickham
> (<h.wickham at gmail.com>) escribi?:
> >
> > 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?
> >
> > 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(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
> >
> > It seems like there should be a way to do this that doesn't
require
> > generating a call with missing arguments, but I can't think of it.
>
> The following code seems to work. The only minor drawback is that, for
> the last case, the output is not a data frame.
>
> subset_ROW <- function(x, i) {
> nd <- length(dim(x))
> if (nd <= 1L)
> return(x[i])
> xx <- apply(x, 2:nd, `[`, i, drop=FALSE)
> dim(xx) <- c(length(i), dim(x)[-1])
> xx
> }
>
> I?aki
>
> >
> > Thanks!
> >
> > Hadley
> >
> > --
> > http://hadley.nz
> >
--
I?aki ?car
http://www.enchufa2.es
@Enchufa2
There probably should be an abstraction for this. In S4Vectors, we have extractROWS(). Michael On Fri, 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? > > 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(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 > > It seems like there should be a way to do this that doesn't require > generating a call with missing arguments, but I can't think of it. > > Thanks! > > Hadley > > -- > http://hadley.nz > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >
> 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
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
On 06/08/2018 10:15 AM, Michael Lawrence wrote:> There probably should be an abstraction for this. In S4Vectors, we > have extractROWS().FWIW the code in S4Vectors that does what your subset_ROW() does is: https://github.com/Bioconductor/S4Vectors/blob/04cc9516af986b30445e99fd1337f13321b7b4f6/R/subsetting-utils.R#L466-L476 (This is the default "extractROWS" method.) Except for the normalization of 'i', it does the same as your subset_ROW(). I don't know how to do this without generating a call with missing arguments. H.> > Michael > > On Fri, 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? >> >> 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(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 >> >> It seems like there should be a way to do this that doesn't require >> generating a call with missing arguments, but I can't think of it. >> >> Thanks! >> >> Hadley >> >> -- >> https://urldefense.proofpoint.com/v2/url?u=http-3A__hadley.nz&d=DwICAg&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=MF0DzYDiaYtcFXIyQwpQKs9lVbLNvdBBUubTv7BVAfM&s=GSpoAzc1Kn_BnTIkDh0HBFGKtRm-xFodxEPOejriC9Q&e>> >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://urldefense.proofpoint.com/v2/url?u=https-3A__stat.ethz.ch_mailman_listinfo_r-2Ddevel&d=DwICAg&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=MF0DzYDiaYtcFXIyQwpQKs9lVbLNvdBBUubTv7BVAfM&s=HsEbNAT5IElAUS-W2VVSeJs4tfQc77heV7BbQxru518&e>> > > ______________________________________________ > R-devel at r-project.org mailing list > https://urldefense.proofpoint.com/v2/url?u=https-3A__stat.ethz.ch_mailman_listinfo_r-2Ddevel&d=DwICAg&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=MF0DzYDiaYtcFXIyQwpQKs9lVbLNvdBBUubTv7BVAfM&s=HsEbNAT5IElAUS-W2VVSeJs4tfQc77heV7BbQxru518&e>-- 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