Pavel Krivitsky
2023-Mar-04 00:21 UTC
[Rd] Augment base::replace(x, list, value) to allow list= to be a predicate?
Dear All, Currently, list= in base::replace(x, list, value) has to be an index vector. For me, at least, the most common use case is for list= to be some simple property of elements of x, e.g., x <- c(1,2,NA,3) replace(x, is.na(x), 0) Particularly when using R pipes, which don't allow multiple substitutions, it would simplify many of such cases if list= could be a function that returns an index, e.g., replace <- function (x, list, values, ...) { # Here, list() refers to the argument, not the built-in. if(is.function(list)) list <- list(x, ...) x[list] <- values x } Then, the following is possible: c(1,2,NA,3) |> replace(is.na, 0) Any thoughts? Pavel
Serguei Sokol
2023-Mar-06 08:45 UTC
[Rd] Augment base::replace(x, list, value) to allow list= to be a predicate?
Le 04/03/2023 ? 01:21, Pavel Krivitsky a ?crit?:> Dear All, > > Currently, list= in base::replace(x, list, value) has to be an index > vector. For me, at least, the most common use case is for list= to be > some simple property of elements of x, e.g., > > x <- c(1,2,NA,3) > replace(x, is.na(x), 0) > > Particularly when using R pipes, which don't allow multiple > substitutions,Right, but anonymous function syntax can palliate to this: x |> (\(x) replace(x, is.na(x), 0))()> it would simplify many of such cases if list= could be a > function that returns an index, e.g., > > replace <- function (x, list, values, ...) { > # Here, list() refers to the argument, not the built-in. > if(is.function(list)) list <- list(x, ...) > x[list] <- values > x > }Before modifying the base of R, we should examine existing possibilities to achieve the same goal. In this particular case and if the previous solution (anonymous function) is not satisfactory a thin one-line wrapper can make the job: freplace <- function (x, list, values, ...) replace(x, if(is.function(list)) list <- list(x, ...) else list, values)> > Then, the following is possible: > > c(1,2,NA,3) |> replace(is.na, 0)this becomes c(1,2,NA,3) |> freplace(is.na, 0) and looks quite acceptable for me. Best, Serguei.> > Any thoughts? > Pavel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- Serguei Sokol Ingenieur de recherche INRAE Cellule Math?matiques TBI, INSA/INRAE UMR 792, INSA/CNRS UMR 5504 135 Avenue de Rangueil 31077 Toulouse Cedex 04 tel: +33 5 61 55 98 49 email: sokol at insa-toulouse.fr http://www.toulouse-biotechnology-institute.fr/en/technology_platforms/mathematics-cell.html
Gabor Grothendieck
2023-Mar-07 12:33 UTC
[Rd] Augment base::replace(x, list, value) to allow list= to be a predicate?
This could be extended to sub and gsub as well which gsubfn in the gusbfn package already does: library(gsubfn) gsubfn("^..", toupper, c("abc", "xyz")) ## [1] "ABc" "XYz" On Fri, Mar 3, 2023 at 7:22?PM Pavel Krivitsky <p.krivitsky at unsw.edu.au> wrote:> > Dear All, > > Currently, list= in base::replace(x, list, value) has to be an index > vector. For me, at least, the most common use case is for list= to be > some simple property of elements of x, e.g., > > x <- c(1,2,NA,3) > replace(x, is.na(x), 0) > > Particularly when using R pipes, which don't allow multiple > substitutions, it would simplify many of such cases if list= could be a > function that returns an index, e.g., > > replace <- function (x, list, values, ...) { > # Here, list() refers to the argument, not the built-in. > if(is.function(list)) list <- list(x, ...) > x[list] <- values > x > } > > Then, the following is possible: > > c(1,2,NA,3) |> replace(is.na, 0) > > Any thoughts? > Pavel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com
Pavel Krivitsky
2023-Mar-19 06:33 UTC
[Rd] [WARNING: POTENTIAL FORGED EMAIL] Augment base::replace(x, list, value) to allow list= to be a predicate?
Dear All, Following up on this, I was wondering whether it might be possible to get a disposition from R developers. I did find a way to produce a similar effect reasonably concisely using call alchemy and lazy evaluation. The following function grabs the specified arguments in the function whose argument it is, applies the specified function to them, and returns the result. I am not sure if it correctly handles all possible cases, particularly when nonstandard evaluation and functions with side-effects are involved. .af. <- function(...){ if(is.numeric(arg1 <- ...elt(1)) || is.character(arg1)){ # By position or name i <- arg1 f <- ...elt(2L) g <- \(x, dummy1, dummy2, ...) f(x, ...) # Eat 2 arguments in ... . }else{ # First argument (the default) i <- 1L f <- arg1 g <- \(x, dummy, ...) f(x, ...) # Eat 1 argument in ... . } sys.function(1L) |> formals() |> names() |> setNames(nm=_) |> (`[`)(i) |> get(sys.frame(1L)) |> g(...) } # Examples: c(1,2,NA,3) |> replace(.af.(is.na), 0) # First argument 1:5 |> replace(.af.(`>`, 3), 0) # Function of multiple arguments 1:5 |> ifelse(.af.(2, `>`, 3), yes=_, 0) # Specify position of referenced argument 1:5 |> ifelse(.af.("yes", `>`, 3), yes=_, 0) # Specify name of referenced argument It may also make sense to have hard-coded versions of this for common cases, e.g., .a2f. <- function(...) .af.(2L, ...) I am not sure how readable or concise this is in practice, and I don't think this should go into R proper, but would anyone else use it if I put something like this in a package? Best Regards, Pavel On Sat, 2023-03-04 at 00:21 +0000, r-devel-bounces at r-project.org wrote:> Dear All, > > Currently, list= in base::replace(x, list, value) has to be an index > vector. For me, at least, the most common use case is for list= to be > some simple property of elements of x, e.g., > > x <- c(1,2,NA,3) > replace(x, is.na(x), 0) > > Particularly when using R pipes, which don't allow multiple > substitutions, it would simplify many of such cases if list= could be > a > function that returns an index, e.g., > > replace <- function (x, list, values, ...) { > ? # Here, list() refers to the argument, not the built-in. > ? if(is.function(list)) list <- list(x, ...) > ? x[list] <- values > ? x > } > > Then, the following is possible: > > c(1,2,NA,3) |> replace(is.na, 0) > > ????????????????????????Any thoughts? > ????????????????????????Pavel > ______________________________________________ > R-devel at r-project.org?mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
Possibly Parallel Threads
- Augment base::replace(x, list, value) to allow list= to be a predicate?
- rhub vs. CRAN fedora-*-devel, using armadillo & slapack
- rhub vs. CRAN fedora-*-devel, using armadillo & slapack
- xyTable(x,y) versus table(x,y) with NAs
- rhub vs. CRAN fedora-*-devel, using armadillo & slapack