1

I need to compute every number in B with every number in A and every number in m0 with the formula in fun. By applyingge <- lapply(B,fun) I can compute every number in A with every number in B if m0 is a single number. How should I do if I have more than one m0 now as specified in the codes?

I think even for computing various B and A but single m0, what I did here with lapply in a function and then lapply again is not a smart way.

The expected output is a list with values in B computed with different numbers of A and m0.

This is the structure of ge when m0 is a single value.

enter image description here


fun <- function (i){
  res <- lapply(A, function(x){
    g <- as.matrix (m0 * (-x * i))})}
ge <- lapply(B, fun)

m0 <- c(10,20)
A <- c(1,2)
B <- list(per1 = structure(list(t1 = c(1,2), t2 = c(3,4)), row.names = c(NA, 
                                                                        -2L), class = "data.frame"),
          per2 = structure(list(t1 = c(10,20), t2 = c(30,40)), row.names = c(NA, 
                                                                         -2L), class = "data.frame"))
Kenny
  • 361
  • 1
  • 8
  • There is at least a curly brace missing in your example code. Please make sure the MRE is actually working. – dario Feb 10 '21 at 13:39
  • @dario really sorry! I have fixed the typo. – Kenny Feb 10 '21 at 13:42
  • Hi Shepard. It seems you aren't getting much help so far. If you add a much simpler MRE (with only as complicated data.structures and function as absolutely necessary to replicate your problem, which as I understand it has nothing to do with the actual math or the size of the datasets) I might give it a try. But as the question stands now it would be way to time consuming for me to figure this out. (Just an offer, feel free to ignore) – dario Feb 10 '21 at 15:58
  • Hello Dario, thank you very much for this suggestion. I think it's because my initial data is too huge and the function is too massy which gave me a illusion that my example is mini enough. I have changed the data set and made it simpler. – Kenny Feb 10 '21 at 16:29
  • What is the expected output? A mutlidimensional matrix? This post on [minimale reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610#5963610) is quite important. The MRE (which included expected output) will make it easier for others to find and test a answer to your question. – dario Feb 10 '21 at 16:50
  • The expected output is a list like `ge`, `ge` is a list with different values of `A` computed with every numbers in `B` but with only one `m0` (it will work if we change `m0` to a single value), what I expected now is a list with different values of `m0` computed with different values of `A` and `B` . So it will be a list with `B` computed by different number of `A` and `m0` – Kenny Feb 10 '21 at 16:56
  • @Yuri Sarakin beat me to it with his excellent solutions. But great that you got an answer! – dario Feb 10 '21 at 17:35
  • @dario Thank you still for spending time helping to find the solutions!! – Kenny Feb 10 '21 at 17:55

1 Answers1

2

if I understood you correctly

base

m0 <- c(10, 20)
A <- c(1,2)
B <- list(
  per1 = structure(list(t1 = c(1, 2), t2 = c(3, 4)),
    row.names = c(NA, -2L),
    class = "data.frame"
  ),
  per2 = structure(list(t1 = c(10, 20), t2 = c(30, 40)),
    row.names = c(NA, -2L),
    class = "data.frame"
  )
)

fun <- function (i){
  lapply(A, function(x){
    lapply(m0, function(y) y * (-x * i)
    )
  }
  )
}

lapply(B, fun)
#> $per1
#> $per1[[1]]
#> $per1[[1]][[1]]
#>    t1  t2
#> 1 -10 -30
#> 2 -20 -40
#> 
#> $per1[[1]][[2]]
#>    t1  t2
#> 1 -20 -60
#> 2 -40 -80
...

Created on 2021-02-10 by the reprex package (v1.0.0)

using tidyverse 1

library(tidyverse)
m0 <- c(10, 20)
A <- c(1, 2)
B <- list(
  per1 = structure(list(t1 = c(1, 2), t2 = c(3, 4)),
    row.names = c(NA, -2L),
    class = "data.frame"
  ),
  per2 = structure(list(t1 = c(10, 20), t2 = c(30, 40)),
    row.names = c(NA, -2L),
    class = "data.frame"
  )
)
df_expand <- expand_grid(A, m0, B) 

fn <- function(A, m0, B) {
  m0 * (-A * B)
}

res <- pmap(df_expand, fn)
nm <- with(df_expand, paste0(names(B), "-A", A, "-m0_",m0))
purrr::set_names(res, nm)
#> $`per1-A1-m0_10`
#>    t1  t2
#> 1 -10 -30
#> 2 -20 -40
#> 
#> $`per2-A1-m0_10`
#>     t1   t2
#> 1 -100 -300
#> 2 -200 -400

Created on 2021-02-10 by the reprex package (v1.0.0)

using tidyverse 2

library(tidyverse)
m0 <- c(10, 20)
A <- c(1, 2)
B <- list(
  per1 = structure(list(t1 = c(1, 2), t2 = c(3, 4)),
                   row.names = c(NA, -2L),
                   class = "data.frame"
  ),
  per2 = structure(list(t1 = c(10, 20), t2 = c(30, 40)),
                   row.names = c(NA, -2L),
                   class = "data.frame"
  )
)
map(m0, function(z) map(-A, function(x) map(B, function(y) x * y * z)))  
#> [[1]]
#> [[1]][[1]]
#> [[1]][[1]]$per1
#>    t1  t2
#> 1 -10 -30
#> 2 -20 -40
#> 
#> [[1]][[1]]$per2
#>     t1   t2
#> 1 -100 -300
#> 2 -200 -400

Created on 2021-02-10 by the reprex package (v1.0.0)

Yuriy Saraykin
  • 8,390
  • 1
  • 7
  • 14
  • Thank you so much for these excellent solutions! May I ask if I can structure the data as lists in lists for the `tidyverse` solution like the results in the first solution? – Kenny Feb 10 '21 at 18:11
  • As to know the results are computed by which combination of `A`, `m0`, and `B`. – Kenny Feb 10 '21 at 18:20