Reputation:
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
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