user7905871
user7905871

Reputation:

for over list with different lengths in lapply

I have complicated function which includes many lists with different lengths. I would like to pass the same function over these lists using lapply but I got NULL. I know my problem but do not know how to fix it.

My first problem is here:

AFA <- lapply(1:m, function(i) A[[i]][AA[[i]]])

AFA is a list of two elements. Each element of list contains 10 elements.

FA <- lapply(1:m, function(i) { which(AFA[[i]][[j]] %in% c(2, 7))})

FA tried to see which elements of the 10 elements are 2 or 7.

I know that lapply here is not help. But I could not use mapply in this case.

My second problem is:

`lapply(nAA2, function(x) if (x > 0) { ##if the length of the function is not zero.

      for(j in 1:m){
        for (i in 1:x) ....` 

nAA2 is a list of two elements. The length of the first element is 1 while 2 for the second element. Hence, the code says this:

for the length of the first element. if (AFA[[j]][[FA[[i]]]] == 2) this means, check each element of AFA using FA and since FA is also a list then I used FA[[i]].

Instead to say:

for ( i in 1:length(nAA2[[1]]) .... and for ( i in 1:length(nAA2[[2]]) ....

I would like to merge then in one code.

Here is my full code with my comments explaining the code lines:

A1 <- c(0, 2, 3, 4, 4,
        0, 0, 3, 4, 1,
        0, 0, 0, 4, 1,
        0, 0, 0, 0, 3,
        0, 0, 0, 0, 0)
A1  <- matrix(A1, 5, 5)
A2 <- c(0, 2, 3, 2, 4,
        0, 0, 3, 4, 1,
        0, 0, 0, 4, 1,
        0, 0, 0, 0, 3,
        0, 0, 0, 0, 0)
A2  <- matrix(A2, 5, 5)

A <- list(A1, A2)
m <- length(A)

AA <- lapply(A, function(x) x > 0)
AA2 <- lapply(A, function(x) x %in% c(2, 7))

AA[is.na(AA)] <- FALSE
AA2[is.na(AA2)] <- FALSE

nAA <- lapply(AA, function(x) sum(x, na.rm = TRUE))
nAA2 <- lapply(AA2, function(x) sum(x, na.rm = TRUE))

AFA <- lapply(1:m, function(i) A[[i]][AA[[i]]])
llA <- lapply(1:m, function(i) double(nAA[[i]]+nAA2[[i]]))
luA <- lapply(1:m, function(i) double(nAA[[i]]+nAA2[[i]]))
FA <-  lapply(1:m, function(i) { which(AFA[[i]][[j]] %in% c(2, 7))}) ## here 
AFA is a list of two elements. I would like to access the first element of 
the list,  and then check each element. I know this is wrong, but how to fix 
it with `mapply`. 


for(j in 1:m){

}
lapply(nAA2, function(x) if (x > 0) { ##here to check that they are not zero. That is we have number equal to 2 or 7.

  for(j in 1:m){ 
    for (i in 1:x) { #here I wouldl like to loop over the length of the 
    first list and then the second list.
      if (AFA[[j]][[FA[[i]]]] == 2) {
        # t
        llA[[j]][nAA[[i]] + i] <- 2
        luA[[j]][nAA[[i]] + i] <- 5 
      }

The expected output should be like this:

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


[[2]][[1]]
5
[[2]][[2]]
5

Upvotes: 3

Views: 2516

Answers (1)

LAP
LAP

Reputation: 6685

Partial answer (only first problem):

FA <- lapply(1:m, function(i) { which(AFA[[i]][[j]] %in% c(2, 7))})

FA tried to see which elements of the 10 elements are 2 or 7.

I think you are using lapply the wrong way. lapply loops over every object in a list, so to identify the vector elements which are either 2 or 7, just use

FA <-  lapply(AFA, function(x) which(x %in% c(2, 7)))

> FA
[[1]]
[1] 1

[[2]]
[1] 1 3

The output shows you the positions of vector elements that are either 2 or 7 in the both vectors of list AFA.

Solution for problem 2:

To be able to perform multiple tests and assign the corresponding values wo luA and llA, we first create new lists/vectors.

An example:

testvalues <- list(2, c(7, 10), c(3, 5))
llAvalues <- c(2, 1, 3)
luAvalues <- c(5, 2, 4)

These include the values to be tested for in testvalues, and the values to be given to llA and luA for the corresponding tests. The new objects must have the same lengths!

Now we use a nested mapply call to loop through AFA on the outer level, and through each test on the inner level.

llA <- mapply(function(v, w) mapply(function(x,y) ifelse(v[w] %in% x, y, 0), testvalues, llAvalues), AFA, FA)
luA <- mapply(function(v, w) mapply(function(x,y) ifelse(v[w] %in% x, y, 0), testvalues, luAvalues), AFA, FA)

Afterwards, we delete all generated 0 (could also use NA).

llA <- lapply(llA, function(x) x[x != 0])

which leaves us with the desired output.

Upvotes: 3

Related Questions