[R] Reduce(paste, x) question

Brian Diggs diggsb at ohsu.edu
Tue Nov 6 22:11:17 CET 2012


On 11/1/2012 1:06 PM, mdvaan wrote:
> I should have been more specific:
>
> y <- list()
> a <- c("A", "K")
> b <- c("B", "L")
> c <- c("C", "M")
> d <- c("D", "N")
> e <- c("E", "O")
>
> y[[1]] <- a
> y[[2]] <- b
> y[[3]] <- c
> y[[4]] <- d
> y[[5]] <- e
>
> y
> [[1]]
> [1] "A" "K"
>
> [[2]]
> [1] "B" "L"
>
> [[3]]
> [1] "C" "M"
>
> [[4]]
> [1] "D" "N"
>
> [[5]]
> [1] "E" "O"
>
> How do I get a list object like y (each element of y is a vector of strings)
> from:
>
> x[[1]] <- LETTERS[1:5]
> x[[2]] <- LETTERS[11:15]
>
> using only the Reduce function?
>
> Thanks!

If you are not bound to use the Reduce function, then a simple approach 
is just

library("plyr")
alply(do.call(cbind,x), 1)

If you need it to match in terms of names and everything, wrapping that 
in and unclass and unname will give exactly y

 > x
[[1]]
[1] "A" "B" "C" "D" "E"

[[2]]
[1] "K" "L" "M" "N" "O"

 > y
[[1]]
[1] "A" "K"

[[2]]
[1] "B" "L"

[[3]]
[1] "C" "M"

[[4]]
[1] "D" "N"

[[5]]
[1] "E" "O"

 > identical(y, unclass(unname(alply(do.call(cbind,x), 1))))
[1] TRUE

Now, if you _really_ want to use Reduce, you can. But it is trickier 
because of the properties that the function used in Reduce must have. 
Most specifically, the function used in Reduce must return a value which 
has the same structure as it takes in its first argument. Its second 
argument must have the structure of each piece of the variable being fed in.

In your case, the return value is a list of length equal to the original 
vectors of each element of x. So the first argument to the function used 
in Reduce must be a list. The second argument is a vector. The function 
must add each element of the vector to the vector in the corresponding 
position of the list.

bnd <- function(x1, x2) {
   lapply(seq_along(x1), function(i) {
     c(x1[[i]], x2[[i]])
   })
}

Now this function can be used in the Reduce function, if an init value 
is specified that acts as an identity under bnd and is of the correct 
structure (list of appropriate length); a list of NULLs will work

Reduce(bnd, x, init=replicate(length(x[[1]]), NULL))

Both methods appropriately handle longer x's

 > x[[3]] <- LETTERS[21:25]
 > unclass(unname(alply(do.call(cbind,x), 1)))
[[1]]
[1] "A" "K" "U"

[[2]]
[1] "B" "L" "V"

[[3]]
[1] "C" "M" "W"

[[4]]
[1] "D" "N" "X"

[[5]]
[1] "E" "O" "Y"

 > Reduce(bnd, x, init=replicate(length(x[[1]]), NULL))
[[1]]
[1] "A" "K" "U"

[[2]]
[1] "B" "L" "V"

[[3]]
[1] "C" "M" "W"

[[4]]
[1] "D" "N" "X"

[[5]]
[1] "E" "O" "Y"

The only reason that you _must_ use Reduce is that this is a homework 
question, in which case I may have said too much.

> --
> View this message in context: http://r.789695.n4.nabble.com/Reduce-paste-x-question-tp4648151p4648169.html
> Sent from the R help mailing list archive at Nabble.com.
>
-- 
Brian S. Diggs, PhD
Senior Research Associate, Department of Surgery
Oregon Health & Science University




More information about the R-help mailing list