Wow! Yes, this is very clever -- way too clever for me -- and meets my criteria for a solution. I think it's also another piece of evidence of why piping in base R is not suited for complex/nested assignments, as discussed in Deepayan's response. Maybe someone could offer a better Tidydata piping solution just for completeness? Best, Bert On Sun, Jul 21, 2024 at 7:48?AM Gabor Grothendieck <ggrothendieck at gmail.com> wrote:> > This > - is non-destructive (does not change z) > - passes the renamed z onto further pipe legs > - does not use \(x)... > > It works by boxing z, operating on the boxed version and then unboxing it. > > z <- data.frame(a = 1:3, b = letters[1:3]) > z |> list(x = _) |> within(names(x)[2] <- "foo") |> _$x > ## a foo > ## 1 1 a > ## 2 2 b > ## 3 3 c > > On Sat, Jul 20, 2024 at 4:07?PM Bert Gunter <bgunter.4567 at gmail.com> wrote: > > > > This post is likely pretty useless; it is motivated by a recent post > > from "Val" that was elegantly answered using Tidyverse constructs, but > > I wondered how to do it using base R only. Along the way, I ran into > > the following question to which I think my answer (below) is pretty > > awful. I would be interested in more elegant base R approaches. So... > > > > z <- data.frame(a = 1:3, b = letters[1:3]) > > > z > > a h > > 1 1 a > > 2 2 b > > 3 3 c > > > > Suppose I want to change the name of the second column of z from 'b' > > to 'foo' . This is very easy using nested function syntax by: > > > > names(z)[2] <- "foo" > > > z > > a foo > > 1 1 a > > 2 2 b > > 3 3 c > > > > Now suppose I wanted to do this using |> syntax, along the lines of: > > > > z |> names()[2] <- "foo" ## throws an error > > > > Slightly fancier is: > > > > z |> (\(x)names(x)[2] <- "b")() > > ## does nothing, but does not throw an error. > > > > However, the following, which resulted from a more careful read of > > ?names works (after changing the name of the second column back to "b" > > of course): > > > > z |>(\(x) "names<-"(x,value = "[<-"(names(x),2,'foo')))() > > >z > > a foo > > 1 1 a > > 2 2 b > > 3 3 c > > > > This qualifies to me as "pretty awful." I'm sure there are better ways > > to do this using pipe syntax, so I would appreciate any better > > approaches. > > > > Best, > > Bert > > > > ______________________________________________ > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > > https://stat.ethz.ch/mailman/listinfo/r-help > > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > > and provide commented, minimal, self-contained, reproducible code. > > > > -- > Statistics & Software Consulting > GKX Group, GKX Associates Inc. > tel: 1-877-GKX-GROUP > email: ggrothendieck at gmail.com
hmmm... But note that you still used the nested assignment, names()[2] <- "foo", to circumvent R's pipe limitations, which is exactly what Iris's solution avoids. So I think I was overawed by your cleverness ;-) Best, Bert On Sun, Jul 21, 2024 at 8:01?AM Bert Gunter <bgunter.4567 at gmail.com> wrote:> > Wow! > Yes, this is very clever -- way too clever for me -- and meets my > criteria for a solution. > > I think it's also another piece of evidence of why piping in base R is > not suited for complex/nested assignments, as discussed in Deepayan's > response. > > Maybe someone could offer a better Tidydata piping solution just for > completeness? > > Best, > Bert > > On Sun, Jul 21, 2024 at 7:48?AM Gabor Grothendieck > <ggrothendieck at gmail.com> wrote: > > > > This > > - is non-destructive (does not change z) > > - passes the renamed z onto further pipe legs > > - does not use \(x)... > > > > It works by boxing z, operating on the boxed version and then unboxing it. > > > > z <- data.frame(a = 1:3, b = letters[1:3]) > > z |> list(x = _) |> within(names(x)[2] <- "foo") |> _$x > > ## a foo > > ## 1 1 a > > ## 2 2 b > > ## 3 3 c > > > > On Sat, Jul 20, 2024 at 4:07?PM Bert Gunter <bgunter.4567 at gmail.com> wrote: > > > > > > This post is likely pretty useless; it is motivated by a recent post > > > from "Val" that was elegantly answered using Tidyverse constructs, but > > > I wondered how to do it using base R only. Along the way, I ran into > > > the following question to which I think my answer (below) is pretty > > > awful. I would be interested in more elegant base R approaches. So... > > > > > > z <- data.frame(a = 1:3, b = letters[1:3]) > > > > z > > > a h > > > 1 1 a > > > 2 2 b > > > 3 3 c > > > > > > Suppose I want to change the name of the second column of z from 'b' > > > to 'foo' . This is very easy using nested function syntax by: > > > > > > names(z)[2] <- "foo" > > > > z > > > a foo > > > 1 1 a > > > 2 2 b > > > 3 3 c > > > > > > Now suppose I wanted to do this using |> syntax, along the lines of: > > > > > > z |> names()[2] <- "foo" ## throws an error > > > > > > Slightly fancier is: > > > > > > z |> (\(x)names(x)[2] <- "b")() > > > ## does nothing, but does not throw an error. > > > > > > However, the following, which resulted from a more careful read of > > > ?names works (after changing the name of the second column back to "b" > > > of course): > > > > > > z |>(\(x) "names<-"(x,value = "[<-"(names(x),2,'foo')))() > > > >z > > > a foo > > > 1 1 a > > > 2 2 b > > > 3 3 c > > > > > > This qualifies to me as "pretty awful." I'm sure there are better ways > > > to do this using pipe syntax, so I would appreciate any better > > > approaches. > > > > > > Best, > > > Bert > > > > > > ______________________________________________ > > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > > > https://stat.ethz.ch/mailman/listinfo/r-help > > > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > > > and provide commented, minimal, self-contained, reproducible code. > > > > > > > > -- > > Statistics & Software Consulting > > GKX Group, GKX Associates Inc. > > tel: 1-877-GKX-GROUP > > email: ggrothendieck at gmail.com
The tidy solution is rename literally: z |> rename(foo = 2) Or you could do it with other functions z |> select ( 1, foo = 2) Or z |> mutate( foo = 2 ) |> # untested (always worry that makes the whole column 2) select (-2) But that's akin to z$foo <- z[2] z[2] <- null On Sun, 21 Jul 2024, 16:01 Bert Gunter, <bgunter.4567 at gmail.com> wrote:> Wow! > Yes, this is very clever -- way too clever for me -- and meets my > criteria for a solution. > > I think it's also another piece of evidence of why piping in base R is > not suited for complex/nested assignments, as discussed in Deepayan's > response. > > Maybe someone could offer a better Tidydata piping solution just for > completeness? > > Best, > Bert > > On Sun, Jul 21, 2024 at 7:48?AM Gabor Grothendieck > <ggrothendieck at gmail.com> wrote: > > > > This > > - is non-destructive (does not change z) > > - passes the renamed z onto further pipe legs > > - does not use \(x)... > > > > It works by boxing z, operating on the boxed version and then unboxing > it. > > > > z <- data.frame(a = 1:3, b = letters[1:3]) > > z |> list(x = _) |> within(names(x)[2] <- "foo") |> _$x > > ## a foo > > ## 1 1 a > > ## 2 2 b > > ## 3 3 c > > > > On Sat, Jul 20, 2024 at 4:07?PM Bert Gunter <bgunter.4567 at gmail.com> > wrote: > > > > > > This post is likely pretty useless; it is motivated by a recent post > > > from "Val" that was elegantly answered using Tidyverse constructs, but > > > I wondered how to do it using base R only. Along the way, I ran into > > > the following question to which I think my answer (below) is pretty > > > awful. I would be interested in more elegant base R approaches. So... > > > > > > z <- data.frame(a = 1:3, b = letters[1:3]) > > > > z > > > a h > > > 1 1 a > > > 2 2 b > > > 3 3 c > > > > > > Suppose I want to change the name of the second column of z from 'b' > > > to 'foo' . This is very easy using nested function syntax by: > > > > > > names(z)[2] <- "foo" > > > > z > > > a foo > > > 1 1 a > > > 2 2 b > > > 3 3 c > > > > > > Now suppose I wanted to do this using |> syntax, along the lines of: > > > > > > z |> names()[2] <- "foo" ## throws an error > > > > > > Slightly fancier is: > > > > > > z |> (\(x)names(x)[2] <- "b")() > > > ## does nothing, but does not throw an error. > > > > > > However, the following, which resulted from a more careful read of > > > ?names works (after changing the name of the second column back to "b" > > > of course): > > > > > > z |>(\(x) "names<-"(x,value = "[<-"(names(x),2,'foo')))() > > > >z > > > a foo > > > 1 1 a > > > 2 2 b > > > 3 3 c > > > > > > This qualifies to me as "pretty awful." I'm sure there are better ways > > > to do this using pipe syntax, so I would appreciate any better > > > approaches. > > > > > > Best, > > > Bert > > > > > > ______________________________________________ > > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > > > https://stat.ethz.ch/mailman/listinfo/r-help > > > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > > > and provide commented, minimal, self-contained, reproducible code. > > > > > > > > -- > > Statistics & Software Consulting > > GKX Group, GKX Associates Inc. > > tel: 1-877-GKX-GROUP > > email: ggrothendieck at gmail.com > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
Thanks, Calum. That was exactly what Duncan Murdoch proposed earlier in this thread, except, of course, he had to explicitly write the function first. -- Bert On Sun, Jul 21, 2024 at 8:12?AM CALUM POLWART <polc1410 at gmail.com> wrote:> > The tidy solution is rename > > literally: > > z |> rename(foo = 2) > > Or you could do it with other functions > > z |> select ( 1, foo = 2) > > Or > > z |> mutate( foo = 2 ) |> # untested (always worry that makes the whole column 2) > select (-2) > > But that's akin to > > z$foo <- z[2] > z[2] <- null > > > On Sun, 21 Jul 2024, 16:01 Bert Gunter, <bgunter.4567 at gmail.com> wrote: >> >> Wow! >> Yes, this is very clever -- way too clever for me -- and meets my >> criteria for a solution. >> >> I think it's also another piece of evidence of why piping in base R is >> not suited for complex/nested assignments, as discussed in Deepayan's >> response. >> >> Maybe someone could offer a better Tidydata piping solution just for >> completeness? >> >> Best, >> Bert >> >> On Sun, Jul 21, 2024 at 7:48?AM Gabor Grothendieck >> <ggrothendieck at gmail.com> wrote: >> > >> > This >> > - is non-destructive (does not change z) >> > - passes the renamed z onto further pipe legs >> > - does not use \(x)... >> > >> > It works by boxing z, operating on the boxed version and then unboxing it. >> > >> > z <- data.frame(a = 1:3, b = letters[1:3]) >> > z |> list(x = _) |> within(names(x)[2] <- "foo") |> _$x >> > ## a foo >> > ## 1 1 a >> > ## 2 2 b >> > ## 3 3 c >> > >> > On Sat, Jul 20, 2024 at 4:07?PM Bert Gunter <bgunter.4567 at gmail.com> wrote: >> > > >> > > This post is likely pretty useless; it is motivated by a recent post >> > > from "Val" that was elegantly answered using Tidyverse constructs, but >> > > I wondered how to do it using base R only. Along the way, I ran into >> > > the following question to which I think my answer (below) is pretty >> > > awful. I would be interested in more elegant base R approaches. So... >> > > >> > > z <- data.frame(a = 1:3, b = letters[1:3]) >> > > > z >> > > a h >> > > 1 1 a >> > > 2 2 b >> > > 3 3 c >> > > >> > > Suppose I want to change the name of the second column of z from 'b' >> > > to 'foo' . This is very easy using nested function syntax by: >> > > >> > > names(z)[2] <- "foo" >> > > > z >> > > a foo >> > > 1 1 a >> > > 2 2 b >> > > 3 3 c >> > > >> > > Now suppose I wanted to do this using |> syntax, along the lines of: >> > > >> > > z |> names()[2] <- "foo" ## throws an error >> > > >> > > Slightly fancier is: >> > > >> > > z |> (\(x)names(x)[2] <- "b")() >> > > ## does nothing, but does not throw an error. >> > > >> > > However, the following, which resulted from a more careful read of >> > > ?names works (after changing the name of the second column back to "b" >> > > of course): >> > > >> > > z |>(\(x) "names<-"(x,value = "[<-"(names(x),2,'foo')))() >> > > >z >> > > a foo >> > > 1 1 a >> > > 2 2 b >> > > 3 3 c >> > > >> > > This qualifies to me as "pretty awful." I'm sure there are better ways >> > > to do this using pipe syntax, so I would appreciate any better >> > > approaches. >> > > >> > > Best, >> > > Bert >> > > >> > > ______________________________________________ >> > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> > > https://stat.ethz.ch/mailman/listinfo/r-help >> > > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> > > and provide commented, minimal, self-contained, reproducible code. >> > >> > >> > >> > -- >> > Statistics & Software Consulting >> > GKX Group, GKX Associates Inc. >> > tel: 1-877-GKX-GROUP >> > email: ggrothendieck at gmail.com >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code.