Search code examples
rlapplysapply

apply a function to multiple list with common elements in r


I have two list with multiple elements, I want to use these two list and apply a formula(function)

As an example, lets say, I have two list A and B with two elements x, and y (I have 1000's of elements, as an example lets say we have 2 elements x and y)

listA <- list(x=matrix(rnorm(50), nrow=10),
              y=matrix(rnorm(50), nrow=10))
listB <- list(x=matrix(rnorm(5), nrow=1),
              y=matrix(rnorm(5), nrow=1))

for each row I need to apply the following fomualae for each row with same elements in listA and listB and save it in respective list as shown below for 2 rows for list x and y. I need to repat this for all the rwos and multiple lists.

#For list X
# for row 1 listA
abs(listA$x[1,]-listB$x[1,])/(abs(listA$x[1,])+abs(listB$x[1,]))

# for row 2 listB
abs(listA$x[2,]-listB$x[1,])/(abs(listA$x[2,])+abs(listB$x[1,]))

#For list Y
# for row 1
abs(listA$y[1,]-listB$y[1,])/(abs(listA$y[1,])+abs(listB$y[1,]))

# for row 2
abs(listA$y[2,]-listB$y[1,])/(abs(listA$y[2,])+abs(listB$y[1,]))

I have been trying with lapply and mapply but not successful so far.


Solution

  • One attempt using Map and sweep, which I think gives the intended result:

    Map(function(x,y) abs(sweep(x,2,y,FUN="-"))/(sweep(abs(x),2,abs(y),FUN="+")),
        listA,
        listB)
    

    E.g.:

    listA <- list(x=matrix(1:9, nrow=3),
                  y=matrix(1:9, nrow=3))
    listB <- list(x=matrix(1:3, nrow=1),
                  y=matrix(4:6, nrow=1))
    
    Map(function(x,y) abs(sweep(x,2,y,FUN="-"))/(sweep(abs(x),2,abs(y),FUN="+")),
        listA,
        listB)
    
    #$x
    #          [,1]      [,2]      [,3]
    #[1,] 0.0000000 0.3333333 0.4000000
    #[2,] 0.3333333 0.4285714 0.4545455
    #[3,] 0.5000000 0.5000000 0.5000000
    #
    #$y
    #          [,1]       [,2]       [,3]
    #[1,] 0.6000000 0.11111111 0.07692308
    #[2,] 0.3333333 0.00000000 0.14285714
    #[3,] 0.1428571 0.09090909 0.20000000
    

    Matches the long-hand calculations:

    abs(listA$x[1,]-listB$x[1,])/(abs(listA$x[1,])+abs(listB$x[1,]))
    #[1] 0.0000000 0.3333333 0.4000000
    abs(listA$x[2,]-listB$x[1,])/(abs(listA$x[2,])+abs(listB$x[1,]))
    #[1] 0.3333333 0.4285714 0.4545455
    abs(listA$y[1,]-listB$y[1,])/(abs(listA$y[1,])+abs(listB$y[1,]))
    #[1] 0.60000000 0.11111111 0.07692308
    abs(listA$y[2,]-listB$y[1,])/(abs(listA$y[2,])+abs(listB$y[1,]))
    #[1] 0.3333333 0.0000000 0.1428571