From gregor.gorjanc at bfro.uni-lj.si  Thu Aug 31 20:06:23 2006
From: gregor.gorjanc at bfro.uni-lj.si (Gregor Gorjanc)
Date: Thu, 31 Aug 2006 20:06:23 +0200
Subject: [Rd] Wish: keep names in mapply() result
In-Reply-To: <44F62A59.8040301@bfro.uni-lj.si>
References: <44F62A59.8040301@bfro.uni-lj.si>
Message-ID: <44F7251F.2090700@bfro.uni-lj.si>

Hello,

Charles Berry sent me (off-list) his proposal, which I find better
(after slight modification) than mine. I would say that proposed changes
make mapply even more consistent with (some) *apply* funcs in terms of
names. Patches to mapply.R and mapply.Rd are attached. I have runned
make check-all and it seems that there are no problems with this change.
I hope R core will find this worth to apply.

New behaviour without first ... as character:

l <- list(a=1, b=2)
k <- list(1)
mapply(FUN="+", l, k)
a b
2 3

mapply(FUN="+", l, k, USE.NAMES=FALSE)
[1] 2 3

mapply(FUN="+", l, k, SIMPLIFY=FALSE)
$a
[1] 2

$b
[1] 3

mapply(FUN="+", l, k, SIMPLIFY=FALSE, USE.NAMES=FALSE)
[[1]]
[1] 2

[[2]]
[1] 3

New behaviour with first ... as character _with_ names:

l <- c("1", "2")
names(l) <- c("a", "b")
mapply(FUN="paste", l, k)
    a     b
"1 1" "2 1"

mapply(FUN="paste", l, k, USE.NAMES=FALSE)
[1] "1 1" "2 1"

mapply(FUN="paste", l, k, SIMPLIFY=FALSE)
$a
[1] "1 1"

$b
[1] "2 1"

mapply(FUN="paste", l, k, SIMPLIFY=FALSE, USE.NAMES=FALSE)
[[1]]
[1] "1 1"

[[2]]
[1] "2 1"

New behaviour with first ... as character _without_ names:

l <- c("1", "2")
mapply(FUN="paste", l, k)
    1     2
"1 1" "2 1"

mapply(FUN="paste", l, k, USE.NAMES=FALSE)
[1] "1 1" "2 1"

mapply(FUN="paste", l, k, SIMPLIFY=FALSE)
$`1`
[1] "1 1"

$`2`
[1] "2 1"

mapply(FUN="paste", l, k, SIMPLIFY=FALSE, USE.NAMES=FALSE)
[[1]]
[1] "1 1"

[[2]]
[1] "2 1"

Regards, Gregor

Gregor Gorjanc wrote:
> Hello!
> 
> I have noticed that mapply() drops names in R 2.3.1 as well as in
> r-devel. Here is a simple example:
> 
> l <- list(a=1, b=2)
> k <- list(1)
> mapply(FUN="+", l, k)
> [1] 2 3
> mapply(FUN="+", l, k, SIMPLIFY=FALSE)
> [[1]]
> [1] 2
> 
> [[2]]
> [1] 3
> 
> Help page does not indicate that this should happen. Argument USE.NAMES
> does not have any effect here as it used only in a bit special
> situation: "If the first ... argument is character and the result does
> not already have names, use it as the names." But result is always
> without names as shown above. Did I miss any peculiarities?
> 
> This is not consistent with lapply, which keeps names i.e.
> 
> lapply(l, "+", 1)
> $a
> [1] 2
> 
> $b
> [1] 3
> 
> I have attached and copied (at the end) patch proposal against SVN that
> adds names back to the result if x had it (only R as my C is ...). This
> way it would also be consistent with lapply. make check-all seems to be
> happy with changes. Now we get:
> 
> mapply(FUN="+", l, k)
> a b
> 2 3
> 
> mapply(FUN="+", l, k, SIMPLIFY=FALSE)
> $a
> [1] 2
> 
> $b
> [1] 3
> 
> And if we had "character" (with some variations) for first ... then:
> 
> l <- list(a="1", b="2")
> mapply(FUN="paste", l, k)
>     a     b
> "1 1" "2 1"
> 
> l <- list("1", "2")
> mapply(FUN="paste", l, k)
> [1] "1 1" "2 1"
> 
> l <- c("1", "2")
> mapply(FUN="paste", l, k)
>     1     2
> "1 1" "2 1"
> 
> Index: src/library/base/R/mapply.R
> ===================================================================
> --- src/library/base/R/mapply.R (revision 39024)
> +++ src/library/base/R/mapply.R (working copy)
> @@ -3,8 +3,16 @@
>      FUN <- match.fun(FUN)
>      dots <- list(...)
> 
> +    if(!is.null(names(dots[[1]]))) {
> +        isNamed <- TRUE
> +        namesX <- names(dots[[1]])
> +    } else {
> +        isNamed <- FALSE
> +    }
> +
>      answer<-.Call("do_mapply", FUN, dots, MoreArgs, environment(),
>                    PACKAGE="base")
> +    if(isNamed) names(answer) <- namesX
> 
>      if (USE.NAMES && length(dots) && is.character(dots[[1]]) &&
>          is.null(names(answer))) names(answer) <- dots[[1]]
> @@ -47,4 +55,4 @@
>      }
>      formals(FUNV) <- formals(FUN)
>      FUNV
> -}
> \ No newline at end of file
> +}
> 
> 
> 
> ------------------------------------------------------------------------
> 
> Index: src/library/base/R/mapply.R
> ===================================================================
> --- src/library/base/R/mapply.R	(revision 39024)
> +++ src/library/base/R/mapply.R	(working copy)
> @@ -3,8 +3,16 @@
>      FUN <- match.fun(FUN)
>      dots <- list(...)
>  
> +    if(!is.null(names(dots[[1]]))) {
> +        isNamed <- TRUE
> +        namesX <- names(dots[[1]])
> +    } else {
> +        isNamed <- FALSE
> +    }
> +
>      answer<-.Call("do_mapply", FUN, dots, MoreArgs, environment(),
>                    PACKAGE="base")
> +    if(isNamed) names(answer) <- namesX
>  
>      if (USE.NAMES && length(dots) && is.character(dots[[1]]) &&
>          is.null(names(answer))) names(answer) <- dots[[1]]
> @@ -47,4 +55,4 @@
>      }
>      formals(FUNV) <- formals(FUN)
>      FUNV
> -}
> \ No newline at end of file
> +}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: mapply.R.patch.gz
Type: application/x-gzip
Size: 446 bytes
Desc: not available
Url : https://stat.ethz.ch/pipermail/r-devel/attachments/20060831/80849894/attachment-0008.gz 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mapply.Rd.patch.gz
Type: application/x-gzip
Size: 438 bytes
Desc: not available
Url : https://stat.ethz.ch/pipermail/r-devel/attachments/20060831/80849894/attachment-0009.gz 


[Rd] Wish: keep names in mapply() result
Gregor Gorjanc