Match two lists of matrices (row-wisely) in R - r

a and b are two lists in which the object number are the same. The objects containing in both a and b are matrix".
a<-list(matrix(c(1,2,2),1,3),matrix(c(2,1,1,1,2,2),2,3),matrix(,0,3))
b<-list(matrix(c(2,2,2),1,3),matrix(c(1,1,2),1,3),matrix(c(1,2,1),1,3))
> a
[[1]]
[,1] [,2] [,3]
[1,] 1 2 2
[[2]]
[,1] [,2] [,3]
[1,] 2 1 2
[2,] 1 1 2
[[3]]
[,1] [,2] [,3]
> b
[[1]]
[,1] [,2] [,3]
[1,] 2 2 2
[[2]]
[,1] [,2] [,3]
[1,] 1 1 2
[[3]]
[,1] [,2] [,3]
[1,] 1 2 1
From above, we can see there are 3 objects (i.e. matrix) in a and b. The row number in each matrix in list a varies, while the row number in each matrix of list b are the same (nrow=1). I want to compare each row of a with the corresponding row in b, and to calculate how many positions (in respective columns) are the same.
Let's take the second object in both a and b for an example. In a, object 2 is a matrix (ncol=3, nrow=2), we need to compare each row with the second matrix in b. The first row in the second object of a is 2 1 2, we can see that the second and third numbers are the same with the second object in b (1 1 2), so the output is 2, then we continually use the second row (1 1 2) for comparison, we find that the three number are all the same with the object 2 in list b, so the output is 3.
The expected result is as follows:
[[1]]
[1] 2
[[2]]
[1] 2 3
[[3]]
[1] 0
I used the following code to calculate:
Map(function(a,b) matrix(sapply(1:3, function(x) {a[,x]==b[,x]}),ncol=3),a,b)
[[1]]
[,1] [,2] [,3]
[1,] FALSE TRUE TRUE
[[2]]
[,1] [,2] [,3]
[1,] FALSE TRUE TRUE
[2,] TRUE TRUE TRUE
[[3]]
[,1] [,2] [,3]
[1,] Logical,0 Logical,0 Logical,0
But I don't know how to go on to sum the result, since there is Logical,0 in the third object. Could you help me with this? Thank you. Or whether there are other ways to solve this problem. Thanks!

Here's an option:
Map(function(x,y) apply(x, 1, function(z) rowSums(z == y)), a, b)
#[[1]]
#[1] 2
#
#[[2]]
#[1] 2 3
#
#[[3]]
#numeric(0)

Related

How to subset a list of a list based on the name

I am given a list of lists.
I would like now to subset the list based on the names of the sublist.
L1<-list("A"=matrix(c(1:4),2),"B"=matrix(c("a","b","c","d"),2))
L2<-list("A"=matrix(c(5:8),2),"B"=matrix(c("u","v","w","x"),2))
L<-list(L1,L2)
I would now like to select the elements of the sublist according to their name. E.g.
select_names <- c("A")
and obtain a list of lists, whereas the sublist now only contains the elements that have names belonging to 'select_names'. In this case it would be just the element "A":
[[1]]
[[1]]$`A`
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[[2]]$`A`
[,1] [,2]
[1,] 5 7
[2,] 6 8
We can Extract
library(purrr)
map(L, `[`, select_names)
#[[1]]
#[[1]]$A
# [,1] [,2]
#[1,] 1 3
#[2,] 2 4
#[[2]]
#[[2]]$A
# [,1] [,2]
#[1,] 5 7
#[2,] 6 8
Or using lapply
lapply(L, function(x) x[select_names])
Or without anonymous function call
lapply(L, `[`, select_names)
Self promotion. If one is open to using packages, I wrote up a convenience function in the developer version of manymodelr that achieves the same.
manymodelr::get_this(A,L)
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 5 7
[2,] 6 8

How to apply a function on every element of all elements in a list in R

I have a list containing matrices of the same size in R. I would like to apply a function over the same element of all matrices. Example:
> a <- matrix(1:4, ncol = 2)
> b <- matrix(5:8, ncol = 2)
> c <- list(a,b)
> c
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 5 7
[2,] 6 8
Now I want to apply the mean function and would like to get a matrix like that:
[,1] [,2]
[1,] 3 5
[2,] 4 6
One conceptual way to do this would be to sum up the matrices and then take the average value of each entry. Try using Reduce:
Reduce('+', c) / length(c)
Output:
[,1] [,2]
[1,] 3 5
[2,] 4 6
Demo here:
Rextester
Another option is to construct an array and then use apply.
step 1: constructing the array.
Using the abind library and do.call, you can do this:
library(abind)
myArray <- do.call(function(...) abind(..., along=3), c)
Using base R, you can strip out the structure and then rebuild it like this:
myArray <- array(unlist(c), dim=c(dim(a), length(c)))
In both instances, these return the desired array
, , 1
[,1] [,2]
[1,] 1 3
[2,] 2 4
, , 2
[,1] [,2]
[1,] 5 7
[2,] 6 8
step 2: use apply to calculate the mean along the first and second dimensions.
apply(myArray, 1:2, mean)
[,1] [,2]
[1,] 3 5
[2,] 4 6
This will be more flexible than Reduce, since you can swap out many more functions, but it will be slower for this particular application.

frequency distribution of vectors

I have a list of vectors in R (permutations of {1,2,3}) like this:
> Ls
$L
[,1] [,2] [,3]
[1,] 1 2 3
$L
[,1] [,2] [,3]
[1,] 1 2 3
$L
[,1] [,2] [,3]
[1,] 2 1 3
I would like to have a frequency distribution of these vectors, i.e. the desired result should look like: 123 -> 2 and 213 -> 1.
Obviously "Table" cannot do the job. I thought about using a unique identifier for each permutation (eg: hashcoding?) but this would make the original objects unrecognizable. Someone can help?
table(do.call(paste0, do.call(rbind.data.frame, Ls)))
table can do the job~
B=unlist(lapply(LS, paste, collapse = "_"))
table(B)
B
1_2_3 2_3_1
2 1

Creating data frames from list of elements without element names [duplicate]

This question already has answers here:
The difference between bracket [ ] and double bracket [[ ]] for accessing the elements of a list or dataframe
(11 answers)
Closed 7 years ago.
I would like to create a separate dataframe from list of data elements of matrices. For example, I have the following list of matrix elements:-
> A[[1]]
$`up`
,, T+1
[,1] [,2] [,3]
[1,] 2 4 3
[2,] 1 5 7
$`down`
,, T+1
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 2 4 2
$`right`
,,T+1
[,1] [,2] [,3]
[1,] 5 6 7
[2,] 9 2 3
Suppose that I want to create a separate list of data elements. I don't want the element names '$'up'/$'down'/$'right' to appear on my output. With the current code, every time I want to call the first matrix, I have to write the code as
A[[1]]$'up'[,,1] or A[[1]]$'down'[,,1] or A[[1]]$'right'[,,1]
Is it possible to create a separate list so that whenever I want to call it, it would be simpler without the elements name. For example, I just want to call A[[1]], whenever I want to call the first matrix, A[[2]] for the second matrix and so on. It will look something like this:-
> A[[1]]
[,1] [,2] [,3]
[1,] 2 4 3
[2,] 1 5 7
> A[[2]]
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 2 4 2
> A[[3]]
[,1] [,2] [,3]
[1,] 5 6 7
[2,] 9 2 3
With your definition of A you can already access the i-th matrix via A[[i]], e.g.:
> A[[1]]
[,1] [,2] [,3]
[1,] 2 4 3
[2,] 1 5 7
Alternatively you can create a 3-dimensional array, where the third dimension indicates the number of the matrix:
B <- array(do.call("cbind", A), c(2,3,4))
Now you can access the i-th matrix (i-th z-slice of the "cube") via B[,,i], e.g.:
> B[,,2]
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 2 4 2

How can I denominate levels of lists in R?

I would like to denominate the levels of a list, as with rownames() or colnames() when denominating rows and columns of matrices.
Example:
a<-matrix(rep(1,4),2,2)
b<-matrix(rep(2,9),3,3)
list<-list(a,b)
print(list)
Instead of returning [[1]] at the first level I want the list to use some string like 'matrix a' instead. Maybe this is simple to do.
Just use names:
names(list) = c("A","B")
> list
$A
[,1] [,2]
[1,] 1 1
[2,] 1 1
$B
[,1] [,2] [,3]
[1,] 2 2 2
[2,] 2 2 2
[3,] 2 2 2
list[["A"]]
[,1] [,2]
[1,] 1 1
[2,] 1 1
Note that in general it is not good practice to use R reserved words such as list as variable names.

Resources