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
Maybe Matching Threads
- Augment base::replace(x, list, value) to allow list= to be a predicate?
- Augment base::replace(x, list, value) to allow list= to be a predicate?
- 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