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 ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
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 <[hidden email]> 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 > > ______________________________________________ > [hidden email] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel [[alternative HTML version deleted]] ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
In reply to this post by bbolker
> On Jan 4, 2018, at 11:56 AM, Ben Bolker <[hidden email]> 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 ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
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 <[hidden email]> wrote: > > >> On Jan 4, 2018, at 11:56 AM, Ben Bolker <[hidden email]> 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 ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
PS I'm tempted to insert a warning at this point and see how often it
actually gets triggered ... On Thu, Jan 4, 2018 at 4:44 PM, Ben Bolker <[hidden email]> wrote: > 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 <[hidden email]> wrote: >> >> >>> On Jan 4, 2018, at 11:56 AM, Ben Bolker <[hidden email]> 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 ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
In reply to this post by bbolker
> On Jan 4, 2018, at 1:44 PM, Ben Bolker <[hidden email]> wrote: > > Chuck: I don't see how this example represents > incomplete/incommensurate recycling. It doesn't. I took your subject line to be the theme of your posting and `incommensurate lengths' to be an instance used to emphasize how silent recycling might `bite' the user. Chuck ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
In reply to this post by bbolker
I have never used this construct. However, part of my job is seeing how
well CRAN packages work in our reimplementation of the R language and I am continually surprised by the inventiveness of package writers. Bill Dunlap TIBCO Software wdunlap tibco.com On Thu, Jan 4, 2018 at 1:44 PM, Ben Bolker <[hidden email]> wrote: > 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 <[hidden email]> wrote: > > > > > >> On Jan 4, 2018, at 11:56 AM, Ben Bolker <[hidden email]> 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 > [[alternative HTML version deleted]] ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel |
Free forum by Nabble | Edit this page |