GuedesBF
GuedesBF

Reputation: 9878

corresponding comparison of vectors within a list in R

I have a list of 4 logical vectors (mylist):

list(a = c(NA, FALSE, FALSE, TRUE, FALSE, NA, NA, NA, FALSE, 
FALSE, FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, TRUE, TRUE, 
TRUE, TRUE, NA, FALSE, NA, TRUE, FALSE, FALSE, NA, TRUE, FALSE, 
NA, TRUE, NA, TRUE, FALSE, NA, NA, NA, NA, FALSE, NA, NA, NA, 
NA, FALSE, FALSE, TRUE, NA, NA, NA, FALSE, NA, NA, TRUE, NA, 
FALSE, TRUE, NA, FALSE, TRUE, NA, NA, NA, NA, FALSE, NA, FALSE, 
NA, NA, NA, FALSE, TRUE, TRUE, NA, TRUE, NA, NA, FALSE, FALSE, 
TRUE, NA, FALSE, FALSE, FALSE, NA, NA, FALSE, NA, FALSE, NA, 
FALSE, NA, NA, NA, NA, FALSE, NA, TRUE, TRUE, FALSE, TRUE, NA, 
FALSE, TRUE, NA, TRUE, NA, TRUE, FALSE, NA, NA, FALSE, TRUE, 
FALSE, NA, FALSE, NA, TRUE, FALSE, NA, FALSE, FALSE, NA, TRUE, 
TRUE, NA, FALSE, TRUE, FALSE, FALSE, NA, NA, NA, NA, TRUE, FALSE, 
NA, NA, FALSE, NA, NA, NA, NA, NA, TRUE, NA, NA, FALSE, TRUE, 
NA, NA, NA, FALSE, NA, NA, NA, NA, NA, TRUE, TRUE, NA, FALSE, 
NA, NA, FALSE, NA, FALSE, TRUE, TRUE, FALSE, TRUE, NA, TRUE, 
NA, NA), b = c(NA, FALSE, FALSE, FALSE, FALSE, NA, NA, NA, FALSE, 
FALSE, FALSE, FALSE, NA, TRUE, NA, FALSE, TRUE, TRUE, FALSE, 
FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, FALSE, NA, TRUE, FALSE, 
NA, TRUE, NA, FALSE, FALSE, NA, NA, NA, NA, FALSE, NA, NA, NA, 
NA, FALSE, FALSE, TRUE, NA, NA, NA, FALSE, NA, NA, FALSE, NA, 
FALSE, TRUE, NA, FALSE, TRUE, NA, NA, NA, NA, TRUE, NA, FALSE, 
NA, NA, NA, FALSE, TRUE, TRUE, NA, TRUE, NA, NA, FALSE, FALSE, 
FALSE, NA, FALSE, FALSE, FALSE, NA, NA, FALSE, NA, TRUE, NA, 
TRUE, NA, NA, NA, NA, FALSE, NA, TRUE, TRUE, FALSE, FALSE, NA, 
FALSE, FALSE, NA, FALSE, NA, TRUE, FALSE, NA, NA, TRUE, FALSE, 
FALSE, NA, TRUE, NA, FALSE, FALSE, NA, FALSE, TRUE, NA, FALSE, 
FALSE, NA, TRUE, TRUE, FALSE, FALSE, NA, NA, NA, NA, TRUE, FALSE, 
NA, NA, TRUE, NA, NA, NA, NA, NA, FALSE, NA, NA, TRUE, TRUE, 
NA, NA, NA, FALSE, NA, NA, NA, NA, NA, FALSE, FALSE, NA, FALSE, 
NA, NA, FALSE, NA, TRUE, TRUE, FALSE, FALSE, FALSE, NA, FALSE, 
NA, NA), c = c(NA, FALSE, FALSE, FALSE, FALSE, NA, NA, NA, FALSE, 
FALSE, TRUE, FALSE, NA, FALSE, NA, TRUE, TRUE, TRUE, FALSE, FALSE, 
TRUE, NA, TRUE, NA, FALSE, FALSE, FALSE, NA, TRUE, FALSE, NA, 
TRUE, NA, FALSE, FALSE, NA, NA, NA, NA, FALSE, NA, NA, NA, NA, 
FALSE, FALSE, TRUE, NA, NA, NA, FALSE, NA, NA, FALSE, NA, FALSE, 
TRUE, NA, FALSE, FALSE, NA, NA, NA, NA, FALSE, NA, TRUE, NA, 
NA, NA, FALSE, TRUE, TRUE, NA, TRUE, NA, NA, FALSE, FALSE, FALSE, 
NA, FALSE, FALSE, TRUE, NA, NA, FALSE, NA, TRUE, NA, TRUE, NA, 
NA, NA, NA, FALSE, NA, FALSE, TRUE, FALSE, FALSE, NA, TRUE, FALSE, 
NA, FALSE, NA, TRUE, FALSE, NA, NA, FALSE, FALSE, FALSE, NA, 
TRUE, NA, FALSE, FALSE, NA, TRUE, FALSE, NA, FALSE, FALSE, NA, 
TRUE, FALSE, FALSE, FALSE, NA, NA, NA, NA, FALSE, FALSE, NA, 
NA, TRUE, NA, NA, NA, NA, NA, FALSE, NA, NA, TRUE, TRUE, NA, 
NA, NA, FALSE, NA, NA, NA, NA, NA, FALSE, TRUE, NA, FALSE, NA, 
NA, FALSE, NA, FALSE, TRUE, FALSE, FALSE, TRUE, NA, FALSE, NA, 
NA), d = c(NA, FALSE, FALSE, FALSE, FALSE, NA, NA, NA, FALSE, 
FALSE, FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, TRUE, FALSE, 
FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, FALSE, NA, FALSE, 
FALSE, NA, TRUE, NA, FALSE, FALSE, NA, NA, NA, NA, FALSE, NA, 
NA, NA, NA, FALSE, FALSE, TRUE, NA, NA, NA, FALSE, NA, NA, FALSE, 
NA, FALSE, FALSE, NA, FALSE, FALSE, NA, NA, NA, NA, FALSE, NA, 
FALSE, NA, NA, NA, FALSE, TRUE, FALSE, NA, FALSE, NA, NA, FALSE, 
FALSE, TRUE, NA, FALSE, FALSE, FALSE, NA, NA, FALSE, NA, FALSE, 
NA, TRUE, NA, NA, NA, NA, FALSE, NA, FALSE, TRUE, FALSE, FALSE, 
NA, FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, NA, NA, FALSE, 
FALSE, FALSE, NA, FALSE, NA, FALSE, FALSE, NA, TRUE, FALSE, NA, 
FALSE, FALSE, NA, FALSE, FALSE, FALSE, FALSE, NA, NA, NA, NA, 
TRUE, FALSE, NA, NA, FALSE, NA, NA, NA, NA, NA, FALSE, NA, NA, 
FALSE, FALSE, NA, NA, NA, FALSE, NA, NA, NA, NA, NA, FALSE, FALSE, 
NA, FALSE, NA, NA, FALSE, NA, FALSE, FALSE, FALSE, FALSE, FALSE, 
NA, TRUE, NA, NA))

I want a function that would return a logical vector with TRUE values when ANY corresponding value from the original vectors is TRUE (output_vector). When any of the following: (mylist[[1]][[i]], mylist[[2]][[i]], mylist[[3]][[i]], mylist[[4]][[i]]) is TRUE, output_vector[i] should be TRUE.

I came up with two solutions, one with nested for loops, the other with mapply:

#Nested for loops:

my_function<-function(){
        my_vector<-logical(length(mylist[[1]]))
        for (i in 1:length(mylist[[1]])){
                for (j in 1:length(mylist)){
                        my_vector[i]<-any(mylist[[j]][[i]]==T)
                }
        }
my_vector
}

my_function()

mapply:


mapply(any, mylist[[1]], mylist[[2]], mylist[[3]], mylist[[4]])

I am surprised because: 1-) the #mapply and #nested for loops methods yielded different results

Maybe there is something wrong with the nested for loops method? mapply looks much cleaner and wielded results in line with my expectations, though.

bonus question: is there a way to use some sort of do.call() in the mapply method so that I do not have to write out every argument to any()?

Upvotes: 1

Views: 220

Answers (2)

ThomasIsCoding
ThomasIsCoding

Reputation: 102920

Here is another base R option that may apply to your question

colSums(do.call(rbind,mylist))>1

where the number of TRUEs in columns is counted. If there exists a NA, then a NA is returned.

Upvotes: 1

akrun
akrun

Reputation: 887981

If we need an elementwise comparison, use Reduce

out1 <- Reduce(`|`, mylist)

which is similar to the do.call method with Map and any

out2 <- unlist(do.call(Map, c(f = any, mylist)))
all.equal(out1, out2)
#[1] TRUE

In the nested for loop

mylist[[j]][[i]]

is a single element in the list which is getting wrapped with any. Therefore, the my_vector which was initialized as the length of the first vector element of 'mylist' is getting recycled and it will return the output of the last list element

If we make a small change in the function for loop, it would give the same output i.e. the key is to check whether the elements in 'my_vector' at the same position along with the element indexed from 'mylist' have any TRUE values instead of just checking a single element and overwriting it to my_vector

 my_function<-function(){
         my_vector <- logical(length(mylist[[1]]))
         for (i in 1:length(mylist[[1]])){
                 for (j in 1:length(mylist)){
                         my_vector[i] <- any(c(my_vector[i], mylist[[j]][[i]]))
                 }
         }
       my_vector
 }

 out3 <- my_function()
identical(out1, out3)
#[1] TRUE

Upvotes: 1

Related Questions