R - Subsetting list by paramaters of nested list - r

I have a list list_tot that has nested lists.
I want to subset or create a new list that selects specific subsets based on the parameters specified, details follow:
List_1 <- list(a = matrix(5,2), b = matrix(5,7), c = matrix(5,9), d = matrix(5,3))
List_2 <- list(a = matrix(7,3), b = matrix(7,7), c = matrix(7,1), d = matrix(7,9))
List_3 <- list(a = matrix(5,2), b = matrix(5,7), c = matrix(5,9), d = matrix(5,3))
List_4 <- list(a = matrix(5,2), b = matrix(5,7), c = matrix(5,9), d = matrix(5,3))
List_5 <- list(a = matrix(5,2), b = matrix(5,7), c = matrix(5,9), d = matrix(5,3))
List_tot <- list(List_1, List_2, List_3, List_4, List_5)
that reads:
[[1]]
[[1]]$a
[,1]
[1,] 5
[2,] 5
[[1]]$b
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[[1]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[1]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
[[2]]
[[2]]$a
[,1]
[1,] 7
[2,] 7
[3,] 7
[[2]]$b
[,1]
[1,] 7
[2,] 7
[3,] 7
[4,] 7
[5,] 7
[6,] 7
[7,] 7
[[2]]$c
[,1]
[1,] 7
...etc
I want to select:
for each nested list only select list/matrix a, c, and d.
for each nested list select two lists/matrices with the top number of rows.
So New_List_tot would have an output of:
that reads:
[[1]]
[[1]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[1]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
etc...
Any assistance would be helpful. All my attempts, attempts using plyer and dplyr, but with no success and very much stuck.

We can use base R to do this. No packages are needed
lapply(List_tot, `[`, c("a", "c", "d"))
or with anonymous function
lapply(List_tot, function(x) x[c("a", "c", "d")])
if we need the top 2, order the number of rows (lengths work as these are single column matrix, so the number of rows are equal to the total number of elements, get the head of the names of the ordered vector of number of rows and use that to extract the inner list element
lapply(List_tot, function(x) {
x1 <- x[c("a", "c", "d")]
v1 <- lengths(x1)
x1[head(names(v1)[order(-v1)], 2)]
})

Update
For the second goal, you can try
lapply(
List_tot,
function(lst) {
head(lst[c("a", "c", "d")][order(-sapply(lst[c("a", "c", "d")], nrow))], 2)
}
)
which gives
[[1]]
[[1]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[1]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
[[2]]
[[2]]$d
[,1]
[1,] 7
[2,] 7
[3,] 7
[4,] 7
[5,] 7
[6,] 7
[7,] 7
[8,] 7
[9,] 7
[[2]]$a
[,1]
[1,] 7
[2,] 7
[3,] 7
[[3]]
[[3]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[3]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
[[4]]
[[4]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[4]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
[[5]]
[[5]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[5]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
For your first goal "for each nested list only select list/matrix a, c, and d."
lapply(List_tot, `[`, c("a", "c", "d"))
For your second goal "for each nested list select the lists/matrices with the top number of rows."
Map(`[`, List_tot, max.col(t(sapply(List_tot, lengths))))

#akrun has a clean answer for step 1, filtering by columns. For step 2, filtering by number of rows you can try
library(magrittr)
List_colfilter <- lapply(List_tot, function(i)i[c("a","c","d")])
longestlist <- function(l){
maxr <- lapply(l,nrow) %>% unlist %>% max
l2 <- lapply(l, function(x) if(nrow(x)==maxr) x else NA)
for (n in names(l)){
if (is.na(l2[n])){
l2[n] <- NULL
}
}
return(l2)
}
List_longfilter <- lapply(List_colfilter, longestlist)

In base R you could do:
lapply(List_tot,
function(x) (y<-x[c("a", "c", "d")])[order(sapply(y, nrow), decreasing = TRUE)[1:2]])
[[1]]
[[1]]$c
[,1]
[1,] 5
[2,] 5
[3,] 5
[4,] 5
[5,] 5
[6,] 5
[7,] 5
[8,] 5
[9,] 5
[[1]]$d
[,1]
[1,] 5
[2,] 5
[3,] 5
etc

Related

How to convert only row matrices in a list to column matrices in R?

I have a list of matrices where most of the matrices are column matrices but some of them are row matrices. How to convert only those row matrices to column matrices? I would like to achieve this using base R.
Here is the list of matrices where the third one is a row matrix
x <- list(`1` = matrix(1:20, nrow=5), `2` = matrix(1:20, nrow=10), `3` = matrix(1:5, nrow=1))
How to convert the list to one like this:
$`1`
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
$`2`
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
$`3`
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5
I have a much larger dataset and so efficient code is preferred!
Check the dimensions of the matrix and transpose it if the row dimension is 1:
(y <- lapply(x, function(x) if(dim(x)[1] == 1) { t(x)} else x))
# $`1`
# [,1] [,2] [,3] [,4]
# [1,] 1 6 11 16
# [2,] 2 7 12 17
# [3,] 3 8 13 18
# [4,] 4 9 14 19
# [5,] 5 10 15 20
#
# $`2`
# [,1] [,2]
# [1,] 1 11
# [2,] 2 12
# [3,] 3 13
# [4,] 4 14
# [5,] 5 15
# [6,] 6 16
# [7,] 7 17
# [8,] 8 18
# [9,] 9 19
# [10,] 10 20
#
# $`3`
# [,1]
# [1,] 1
# [2,] 2
# [3,] 3
# [4,] 4
# [5,] 5

Conditional subtraction of matrix in R

I am trying to do conditional subtraction of matrices in R. Let's say I have a list of matrices A, B, C. If my selection = 1, then C = A - B. Here are my codes:
selection = 1
A <- matrix(c(1:10), nrow = 5, ncol = 2)
A
B <- matrix(c(11:20), nrow = 5, ncol = 2)
B
C <- matrix(0, nrow = 5, ncol = 2)
C
my_matrix_name <- as.vector(c("A", "B", "C"))
my_list = list(A, B, C)
names(my_list) <- my_matrix_name
my_list$C <- ifelse(selection == 1, my_list$A - my_list$B, "Error")
The above codes yield the following results for my_list:
> my_list
$A
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
$B
[,1] [,2]
[1,] 11 16
[2,] 12 17
[3,] 13 18
[4,] 14 19
[5,] 15 20
$C
[1] -10
But my desired output is like this:
> my_list
$A
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
$B
[,1] [,2]
[1,] 11 16
[2,] 12 17
[3,] 13 18
[4,] 14 19
[5,] 15 20
$C
[,1] [,2]
[1,] -10 -10
[2,] -10 -10
[3,] -10 -10
[4,] -10 -10
[5,] -10 -10
Please help! Thanks!
Use if since the condition that you are checking is scalar and not a vector.
my_list$C <- if(selection == 1) my_list$A - my_list$B else 'Error'
my_list
#$A
# [,1] [,2]
#[1,] 1 6
#[2,] 2 7
#[3,] 3 8
#[4,] 4 9
#[5,] 5 10
#$B
# [,1] [,2]
#[1,] 11 16
#[2,] 12 17
#[3,] 13 18
#[4,] 14 19
#[5,] 15 20
#$C
# [,1] [,2]
#[1,] -10 -10
#[2,] -10 -10
#[3,] -10 -10
#[4,] -10 -10
#[5,] -10 -10

How to rbind a single number with a matrix in R

I tried with the following code
rbind(1, matrix(c(1,2,3,4,5,6,7,8,9,10), 5))
[,1] [,2]
[1,] 1 1
[2,] 1 6
[3,] 2 7
[4,] 3 8
[5,] 4 9
[6,] 5 10
but I wish to get output like below
[,1] [,2]
[1,] 1
[2,] 1 6
[3,] 2 7
[4,] 3 8
[5,] 4 9
[6,] 5 10
cbind a single vector with NA and then use rbind
rbind(cbind(1, NA),matrix(1:10, 5))
# [,1] [,2]
#[1,] 1 NA
#[2,] 1 6
#[3,] 2 7
#[4,] 3 8
#[5,] 4 9
#[6,] 5 10
For purposes of getting the exact output, we can do the following(see the note below):
noquote(rbind(c(1,""),matrix(c(1,2,3,4,5,6,7,8,9,10), 5)))
[,1] [,2]
[1,] 1
[2,] 1 6
[3,] 2 7
[4,] 3 8
[5,] 4 9
[6,] 5 10
NOTE
Using "" to introduce a blank will lead to coercion to character.
We could use as.numeric to have numerics but this would lead to NAs which has already been demonstrated.
Using NA instead of "" is more realistic and useful

ordering matrix by vector correctly

I don't understand why I cannot order a matrix based on a vector using the order function
I have the following:
m
[,1] [,2]
[1,] 1 5
[2,] 2 5
[3,] 3 5
[4,] 4 5
[5,] 5 5
[6,] 6 5
v
[[1]]
[1] 3 1 2 4 5 6
When I use:
m[order(unlist(v)),]
I get the following, incorrectly ordered matrix.
[,1] [,2]
[1,] 2 5
[2,] 3 5
[3,] 1 5
[4,] 4 5
[5,] 5 5
[6,] 6 5
when the order that I want is what's in v
[,1] [,2]
[1,] 3 5
[2,] 1 5
[3,] 2 5
[4,] 4 5
[5,] 5 5
[6,] 6 5
Why do you guys think this is happening and how can I fix it?
Instead of
m[order(unlist(v)),]
Try
temp <- unlist(v)
m[ temp , ]
Because order returns the indexes in the order that you desire. E.g.
> x = c(3,1,2)
> order(x)
[1] 2 3 1
> x[order(x)]
[1] 1 2 3

How to reverse a matrix in R? [duplicate]

This question already has answers here:
Change row order in a matrix/dataframe
(7 answers)
Closed 5 years ago.
I have a simple matrix like:
> a = matrix(c(c(1:10),c(10:1)), ncol=2)
> a
[,1] [,2]
[1,] 1 10
[2,] 2 9
[3,] 3 8
[4,] 4 7
[5,] 5 6
[6,] 6 5
[7,] 7 4
[8,] 8 3
[9,] 9 2
[10,] 10 1
I would like to get this result:
[,1] [,2]
[1,] 10 1
[2,] 9 2
[3,] 8 3
[4,] 7 4
[5,] 6 5
[6,] 5 6
[7,] 4 7
[8,] 3 8
[9,] 2 9
[10,] 1 10
The exact reverse of the matrix. How can I get it?
Thanks
a[nrow(a):1,]
# [,1] [,2]
# [1,] 10 1
# [2,] 9 2
# [3,] 8 3
# [4,] 7 4
# [5,] 6 5
# [6,] 5 6
# [7,] 4 7
# [8,] 3 8
# [9,] 2 9
# [10,] 1 10
Try rev with apply:
> a <- matrix(c(1:10,10:1), ncol=2)
> a
[,1] [,2]
[1,] 1 10
[2,] 2 9
[3,] 3 8
[4,] 4 7
[5,] 5 6
[6,] 6 5
[7,] 7 4
[8,] 8 3
[9,] 9 2
[10,] 10 1
> b <- apply(a, 2, rev)
> b
[,1] [,2]
[1,] 10 1
[2,] 9 2
[3,] 8 3
[4,] 7 4
[5,] 6 5
[6,] 5 6
[7,] 4 7
[8,] 3 8
[9,] 2 9
[10,] 1 10
Here's one way:
a[, rev(seq_len(ncol(a)))]
[,1] [,2]
[1,] 10 1
[2,] 9 2
[3,] 8 3
[4,] 7 4
[5,] 6 5
[6,] 5 6
[7,] 4 7
[8,] 3 8
[9,] 2 9
[10,] 1 10

Resources