[Rd] transform.data.frame() ignores unnamed arguments when no named argument is provided

Sebastian Meyer @eb@meyer @end|ng |rom |@u@de
Thu Mar 2 22:34:33 CET 2023


Note that ?transform.data.frame says arguments need to be named, so you 
are testing unspecified behaviour. I guess this falls in a similar 
category as the note

      If some of the values are not vectors of the appropriate length,
      you deserve whatever you get!

Experiments for a related Problem Report 
(<https://bugs.r-project.org/show_bug.cgi?id=17890>) showed that 
packages bravely ignore the caveats mentioned on the help page, 
including to assume recycling the rows of the input data frame. I didn't 
yet see any uses of unnamed arguments, though.

That said, I agree that transform.data.frame() should be improved. Maybe 
unnamed arguments should always be ignored with a warning. My feeling is 
that these would more often be usage errors than intentional, e.g.:

 > data.frame(a = 1) |> transform(b = 2, a + 2)  # "forgetting" a=
   a b X3
1 1 2  3

I also think the implicit check.names=TRUE behaviour should be disabled. In

 > list2DF(list(`A-1` = 1)) |> transform(B = 2)
   A.1 B
1   1 2

transforming B should not touch the other columns.

I'm less sure about some other forms of undocumented behaviour as 
described in Comment 6 of the linked PR.

	Sebastian Meyer


Am 02.03.23 um 18:49 schrieb Antoine Fabri:
> Dear r-devel,
> 
> See below:
> 
> 
> transform(data.frame(a = 1), 2, 3)
> 
> #>   a
> 
> #> 1 1
> 
> 
> transform(data.frame(a = 1), b=2, 3)
> 
> #>   a b X3
> 
> #> 1 1 2  3
> 
> 
> We need a small modification to make it work consistently, see below:
> 
> 
> transform.data.frame <- function (`_data`, ...) {
> 
>    e <- eval(substitute(list(...)), `_data`, parent.frame())
> 
>    tags <- names(e)
> 
>    ## NEW LINE -----------------------------------------------
> 
>    if (is.null(tags)) tags <- character(length(e))
> 
>    inx <- match(tags, names(`_data`))
> 
>    matched <- !is.na(inx)
> 
>    if (any(matched)) {
> 
>      `_data`[inx[matched]] <- e[matched]
> 
>      `_data` <- data.frame(`_data`)
> 
>    }
> 
>    if (!all(matched))
> 
>      do.call("data.frame", c(list(`_data`), e[!matched]))
> 
>    else `_data`
> 
> }
> 
> 
> transform(data.frame(a = 1), 2, 3)
> 
> #>   a X2 X3
> 
> #> 1 1  2  3
> 
> transform(data.frame(a = 1), b=2, 3)
> 
> #>   a b X3
> 
> #> 1 1 2  3
> 
> 
> Thanks,
> 
> 
> Antoine
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list