Sorry if this has been covered here somewhere in the past, but ... Does anyone know why logical vectors are *silently* recycled, even when they are incommensurate lengths, when doing logical indexing? This is as documented: For ?[?-indexing only: ?i?, ?j?, ?...? can be logical vectors, indicating elements/slices to select. Such vectors are recycled if necessary to match the corresponding extent. but IMO weird:> x <- c(TRUE,TRUE,FALSE) > y <- c(TRUE,FALSE) > x[y][1] TRUE FALSE ## (TRUE, FALSE) gets recycled to (TRUE,FALSE,TRUE) and selects ## the first and third elements If we do logical operations instead we do get a warning:> x | y[1] TRUE TRUE TRUE Warning message: In x | y : longer object length is not a multiple of shorter object length Is it just too expensive to test for incomplete recycling when doing subsetting, or is there a sensible use case for incomplete recycling? Ll. 546ff of main/src/subscript.c suggest that there is a place in the code where we already know if incomplete recycling has happened ... Thoughts? cheers Ben Bolker
One use case is when you want to extract every third item, starting with the second, of an arbitrary vector with x[c(FALSE, TRUE, FALSE)] instead of x[seq_along(x) %% 3 == 2] Bill Dunlap TIBCO Software wdunlap tibco.com On Thu, Jan 4, 2018 at 11:56 AM, Ben Bolker <bbolker at gmail.com> wrote:> > Sorry if this has been covered here somewhere in the past, but ... > > Does anyone know why logical vectors are *silently* recycled, even > when they are incommensurate lengths, when doing logical indexing? This > is as documented: > > For ?[?-indexing only: ?i?, ?j?, ?...? can be logical > vectors, indicating elements/slices to select. Such vectors > are recycled if necessary to match the corresponding extent. > > but IMO weird: > > > x <- c(TRUE,TRUE,FALSE) > > y <- c(TRUE,FALSE) > > x[y] > [1] TRUE FALSE > > ## (TRUE, FALSE) gets recycled to (TRUE,FALSE,TRUE) and selects > ## the first and third elements > > If we do logical operations instead we do get a warning: > > > x | y > [1] TRUE TRUE TRUE > Warning message: > In x | y : longer object length is not a multiple of shorter object length > > Is it just too expensive to test for incomplete recycling when doing > subsetting, or is there a sensible use case for incomplete recycling? > > Ll. 546ff of main/src/subscript.c suggest that there is a place in the > code where we already know if incomplete recycling has happened ... > > Thoughts? > > cheers > Ben Bolker > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel[[alternative HTML version deleted]]
> On Jan 4, 2018, at 11:56 AM, Ben Bolker <bbolker at gmail.com> wrote: > > > Sorry if this has been covered here somewhere in the past, but ... > > Does anyone know why logical vectors are *silently* recycled, even > when they are incommensurate lengths, when doing logical indexing?It is convenient to use a single `TRUE' in programmatic manipulation of subscripts in the same manner as using an empty subscript interactively:> mat<-diag(1:3) > expr1 <- quote(mat[]) > expr1[[3]] <- TRUE > expr1[[4]] <- 2 > eval(expr1)[1] 0 2 0> mat[,2][1] 0 2 0 HTH, Chuck
Hmm. Chuck: I don't see how this example represents incomplete/incommensurate recycling. Doesn't TRUE replicate from length-1 to length-3 in this case (mat[c(TRUE,FALSE),2] would be an example of incomplete recycling)? William: clever, but maybe too clever unless you really need the speed? (The clever way is 8 times faster in the following case ...) x <- rep(1,1e6) rbenchmark::benchmark(x[c(FALSE,TRUE,FALSE)],x[seq_along(x) %% 3 == 2]) On the other hand, it takes 0.025 vs 0.003 seconds per iteration ... fortunes::fortune("7ms") On Thu, Jan 4, 2018 at 4:09 PM, Berry, Charles <ccberry at ucsd.edu> wrote:> > >> On Jan 4, 2018, at 11:56 AM, Ben Bolker <bbolker at gmail.com> wrote: >> >> >> Sorry if this has been covered here somewhere in the past, but ... >> >> Does anyone know why logical vectors are *silently* recycled, even >> when they are incommensurate lengths, when doing logical indexing? > > It is convenient to use a single `TRUE' in programmatic manipulation of subscripts in the same manner as using an empty subscript interactively: > >> mat<-diag(1:3) >> expr1 <- quote(mat[]) >> expr1[[3]] <- TRUE >> expr1[[4]] <- 2 >> eval(expr1) > [1] 0 2 0 >> mat[,2] > [1] 0 2 0 > > HTH, > > Chuck
Reasonably Related Threads
- silent recycling in logical indexing
- Extending each element in a list, or rbind()-ing arrays of different length without recycling
- Add vectors of unequal length without recycling?
- Add vectors of unequal length without recycling?
- text(x, y, labels) - recycling problems and RFC (PR#7084)