7

I am trying to learn different ways to use to the objects inside a list as the FUN arguments in lapply. Take this data:

A <- list(a = matrix(0, ncol = 3, nrow = 3), b = matrix(0, ncol = 3, nrow = 3))
B <- list(a = matrix(1, ncol = 1, nrow = 3), b = matrix(1, ncol = 1, nrow = 3))
D <- mapply(FUN="list", A, B, SIMPLIFY=F, USE.NAMES=F)
D <- lapply(D, `names<-`, c("first", "second"))
D
[[1]]
[[1]]$`first`
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0

[[1]]$second
     [,1]
[1,]    1
[2,]    1
[3,]    1


[[2]]
[[2]]$`first`
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0

[[2]]$second
     [,1]
[1,]    1
[2,]    1
[3,]    1

Desired result:

[[1]]
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0
[4,]    1    1    1

[[2]]
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0
[4,]    1    1    1

This is how I would normally do it:

lapply(D, function(x) rbind(x$first, as.numeric(x$second)))

Now I am wondering whether there is a way to avoid using function(x) and repeating all those xs. Something like:

lapply(D, "rbind", <args>)

How can I let rbind (or any other function) know that I am referring to objects within the frame of lapply?

Thank you,

K.

4
  • 1
    It's usually not possible if you nest several functions (e.g., rbind, as.numeric and $). Commented Aug 24, 2018 at 9:15
  • 1
    You can do something like lapply(D, do.call, what = cbind). The same would work with rbind if you didn't have a one-column matrix but a one-row matrix or vector. Commented Aug 24, 2018 at 9:18
  • @Roland using the same idea, tcbind <- function(...) t(cbind(...)); lapply(D, do.call, what = tcbind) Commented Aug 24, 2018 at 9:23
  • 1
    @agstudy Well, of course, there are practically no limitations if you define a function outside of lapply. But that is not much different from using an anonymous function within lapply. Commented Aug 24, 2018 at 9:26

2 Answers 2

2

To "avoid using function(x) and repeating all those xs", we could use with():

lapply(D, with, rbind(first, as.numeric(second)))
Sign up to request clarification or add additional context in comments.

Comments

1

Update

As per the commments changed the code to keep only the right solution.


As some of the commentators said, the problem is that B would need to be transposed, to find an elegant solution. You should have a look to library(purrr) because with that the whole problem reduces to:

map2(A, B, ~ rbind(.x, t(.y)))
# $`a`
#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    0    0    0
# [3,]    0    0    0
# [4,]    1    1    1

# $b
#      [,1] [,2] [,3]
# [1,]    0    0    0
# [2,]    0    0    0
# [3,]    0    0    0
# [4,]    1    1    1

What map2 does is that it takes 2 lists and applies the function to each element of these lists. The ~ syntax is a shortcut for function(.)

2 Comments

In the same spirit, if we want to operate on D directly, we could: transpose(D) %>% pmap(~ rbind(.x, t(.y)))
Also, the two methods don't produce identical results when the matrix is not just 0s. The upper matrix is transposed with the first method

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.