Gabor Grothendieck
2023-Dec-29 18:45 UTC
[Rd] eval(parse()) within mutate() returning same value for all rows
If the question is how to accomplish this as opposed to how to use eval then we can do it without eval like this provided we can assume that words contains three %s . library(dplyr) library(tidyr) df <- tibble(words=c("%s plus %s equals %s"),args=c("1,1,2","2,2,4","3,3,6")) df |> separate_wider_delim(args, ",", names = c("a", "b", "c")) |> mutate(combined = sprintf(words, a, b, c)) ## # A tibble: 3 ? 5 ## words a b c combined ## <chr> <chr> <chr> <chr> <chr> ## 1 %s plus %s equals %s 1 1 2 1 plus 1 equals 2 ## 2 %s plus %s equals %s 2 2 4 2 plus 2 equals 4 ## 3 %s plus %s equals %s 3 3 6 3 plus 3 equals 6 On Fri, Dec 29, 2023 at 9:14?AM Mateo Obreg?n <obregonmateo at gmail.com> wrote:> > Hi all- > > Looking through stackoverflow for R string combining examples, I found the > following from 3 years ago: > > <https://stackoverflow.com/questions/63881854/how-to-format-strings-using-values-from-other-column-in-r> > > The top answer suggests to use eval(parse(sprintf())). I tried the suggestion > and it did not return the expected combines strings. I thought that this might > be an issue with some leftover values being reused, so I explicitly eval() > with a new.env(): > > > library(dplyr) > > df <- tibble(words=c("%s plus %s equals %s"), > args=c("1,1,2","2,2,4","3,3,6")) > > df |> mutate(combined = eval(parse(text=sprintf("sprintf('%s', %s)", words, > args)), envir=new.env())) > > # A tibble: 3 ? 3 > words args combined > <chr> <chr> <chr> > 1 %s plus %s equals %s 1,1,2 3 plus 3 equals 6 > 2 %s plus %s equals %s 2,2,4 3 plus 3 equals 6 > 3 %s plus %s equals %s 3,3,6 3 plus 3 equals 6 > > The `combined` is not what I was expecting, as the same last eval() is > returned for all three rows. > > Am I missing something? What has changed in the past three years? > > Mateo. > -- > Mateo Obreg?n > > ______________________________________________ > 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
Mateo Obregón
2023-Dec-29 22:31 UTC
[Rd] eval(parse()) within mutate() returning same value for all rows
Thanks Gabor, I like your solution that splits the args into separate columns, in turn making the sprintf() call more interpretable . Cheers. Mateo. -- Mateo Obreg?n On Friday, 29 December 2023 18:45:06 GMT Gabor Grothendieck wrote:> If the question is how to accomplish this as opposed to how to use eval > then we can do it without eval like this provided we can assume that words > contains three %s . > > library(dplyr) > library(tidyr) > df <- tibble(words=c("%s plus %s equals > %s"),args=c("1,1,2","2,2,4","3,3,6")) > > df |> > separate_wider_delim(args, ",", names = c("a", "b", "c")) |> > mutate(combined = sprintf(words, a, b, c)) > ## # A tibble: 3 ? 5 > ## words a b c combined > ## <chr> <chr> <chr> <chr> <chr> > ## 1 %s plus %s equals %s 1 1 2 1 plus 1 equals 2 > ## 2 %s plus %s equals %s 2 2 4 2 plus 2 equals 4 > ## 3 %s plus %s equals %s 3 3 6 3 plus 3 equals 6 > > On Fri, Dec 29, 2023 at 9:14?AM Mateo Obreg?n <obregonmateo at gmail.com>wrote:> > Hi all- > > > > Looking through stackoverflow for R string combining examples, I found the > > following from 3 years ago: > > > > <https://stackoverflow.com/questions/63881854/how-to-format-strings-using-> > values-from-other-column-in-r> > > > > The top answer suggests to use eval(parse(sprintf())). I tried the > > suggestion and it did not return the expected combines strings. I thought > > that this might be an issue with some leftover values being reused, so I > > explicitly eval()> > > with a new.env(): > > > library(dplyr) > > > df <- tibble(words=c("%s plus %s equals %s"), > > > > args=c("1,1,2","2,2,4","3,3,6")) > > > > > df |> mutate(combined = eval(parse(text=sprintf("sprintf('%s', %s)", > > > words, > > > > args)), envir=new.env())) > > > > # A tibble: 3 ? 3 > > > > words args combined > > <chr> <chr> <chr> > > > > 1 %s plus %s equals %s 1,1,2 3 plus 3 equals 6 > > 2 %s plus %s equals %s 2,2,4 3 plus 3 equals 6 > > 3 %s plus %s equals %s 3,3,6 3 plus 3 equals 6 > > > > The `combined` is not what I was expecting, as the same last eval() is > > returned for all three rows. > > > > Am I missing something? What has changed in the past three years? > > > > Mateo. > > -- > > Mateo Obreg?n > > > > ______________________________________________ > > R-devel at r-project.org mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel
Gabor Grothendieck
2023-Dec-30 22:02 UTC
[Rd] eval(parse()) within mutate() returning same value for all rows
Here is a solution that does not hard code 3: library(dplyr) library(purrr) library(tidyr) df %>% separate_wider_delim(args, ",", names_sep = "") %>% mutate(combined = exec(sprintf, .[[1]], !!!.[-1])) ## # A tibble: 3 ? 5 ## words args1 args2 args3 combined ## <chr> <chr> <chr> <chr> <chr> ## 1 %s plus %s equals %s 1 1 2 1 plus 1 equals 2 ## 2 %s plus %s equals %s 2 2 4 2 plus 2 equals 4 ## 3 %s plus %s equals %s 3 3 6 3 plus 3 equals 6 On Fri, Dec 29, 2023 at 1:45?PM Gabor Grothendieck <ggrothendieck at gmail.com> wrote:> > If the question is how to accomplish this as opposed to how to use eval > then we can do it without eval like this provided we can assume that words > contains three %s . > > library(dplyr) > library(tidyr) > df <- tibble(words=c("%s plus %s equals %s"),args=c("1,1,2","2,2,4","3,3,6")) > > df |> > separate_wider_delim(args, ",", names = c("a", "b", "c")) |> > mutate(combined = sprintf(words, a, b, c)) > ## # A tibble: 3 ? 5 > ## words a b c combined > ## <chr> <chr> <chr> <chr> <chr> > ## 1 %s plus %s equals %s 1 1 2 1 plus 1 equals 2 > ## 2 %s plus %s equals %s 2 2 4 2 plus 2 equals 4 > ## 3 %s plus %s equals %s 3 3 6 3 plus 3 equals 6 > > On Fri, Dec 29, 2023 at 9:14?AM Mateo Obreg?n <obregonmateo at gmail.com> wrote: > > > > Hi all- > > > > Looking through stackoverflow for R string combining examples, I found the > > following from 3 years ago: > > > > <https://stackoverflow.com/questions/63881854/how-to-format-strings-using-values-from-other-column-in-r> > > > > The top answer suggests to use eval(parse(sprintf())). I tried the suggestion > > and it did not return the expected combines strings. I thought that this might > > be an issue with some leftover values being reused, so I explicitly eval() > > with a new.env(): > > > > > library(dplyr) > > > df <- tibble(words=c("%s plus %s equals %s"), > > args=c("1,1,2","2,2,4","3,3,6")) > > > df |> mutate(combined = eval(parse(text=sprintf("sprintf('%s', %s)", words, > > args)), envir=new.env())) > > > > # A tibble: 3 ? 3 > > words args combined > > <chr> <chr> <chr> > > 1 %s plus %s equals %s 1,1,2 3 plus 3 equals 6 > > 2 %s plus %s equals %s 2,2,4 3 plus 3 equals 6 > > 3 %s plus %s equals %s 3,3,6 3 plus 3 equals 6 > > > > The `combined` is not what I was expecting, as the same last eval() is > > returned for all three rows. > > > > Am I missing something? What has changed in the past three years? > > > > Mateo. > > -- > > Mateo Obreg?n > > > > ______________________________________________ > > 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-- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com