How to extract sublists based on variable name in R - r

I have lists deep within lists and I want to extract all matrices with name a from the code below and store all these matrices into asingle list, say matlist. Please can anyone suggest how to do this. Thank you in advance
x <- list()
x[[1]] <- list()
x[[1]][[1]] <- list()
x[[1]][[2]] <- list()
x[[2]] <- list()
x[[2]][[1]] <- list()
x[[2]][[2]] <- list()
x[[3]] <- list()
x[[3]][[1]] <- list()
x[[3]][[2]] <- list()
x[[1]][[1]]$a <- matrix(rnorm(4),2,2)
x[[1]][[1]]$b <- 3
x[[1]][[2]]$a <- matrix(rnorm(4),2,2)
x[[1]][[2]]$b <- 3
x[[2]][[1]]$a <- matrix(rnorm(4),2,2)
x[[2]][[1]]$b <- 2
x[[2]][[2]]$a <- matrix(rnorm(4),2,2)
x[[2]][[2]]$b <- 2
x[[3]][[1]]$a <- matrix(rnorm(4),2,2)
x[[3]][[1]]$b <- 1
x[[3]][[2]]$a <- matrix(rnorm(4),2,2)
x[[3]][[2]]$b <- 1

You can use [[ in lapply with a after using unlist for one level to extract lists within lists based on variable name.
matlist <- lapply(unlist(x, FALSE), "[[", "a")
matlist
#[[1]]
# [,1] [,2]
#[1,] -0.2164749 0.1255995
#[2,] 0.9368159 1.0416349
#
#[[2]]
# [,1] [,2]
#[1,] -2.188259 -0.2364393
#[2,] -3.003292 1.2006254
#
#[[3]]
# [,1] [,2]
#[1,] 1.089767 1.059162
#[2,] -2.043437 1.428467
#
#[[4]]
# [,1] [,2]
#[1,] -0.1984872 1.194170
#[2,] -0.9998112 -2.875852
#
#[[5]]
# [,1] [,2]
#[1,] 1.4556923 -0.05156698
#[2,] -0.4252525 -0.64838966
#
#[[6]]
# [,1] [,2]
#[1,] 0.2450849 0.6129029
#[2,] -0.2372427 0.2555269
Or in case you want to keep the structure of sub lists like purrr:map_depth is doing a recursive function call is possible:
f <- function(x, n) {
if(!is.null(names(x)) & n %in% names(x)) x[[n]]
else if(is.list(x)) lapply(x, f, n)
}
matlist <- f(x, "a")
matlist
#[[1]]
#[[1]][[1]]
# [,1] [,2]
#[1,] -0.2164749 0.1255995
#[2,] 0.9368159 1.0416349
#
#[[1]][[2]]
# [,1] [,2]
#[1,] -2.188259 -0.2364393
#[2,] -3.003292 1.2006254
#
#
#[[2]]
#[[2]][[1]]
# [,1] [,2]
#[1,] 1.089767 1.059162
#[2,] -2.043437 1.428467
#
#[[2]][[2]]
# [,1] [,2]
#[1,] -0.1984872 1.194170
#[2,] -0.9998112 -2.875852
#
#
#[[3]]
#[[3]][[1]]
# [,1] [,2]
#[1,] 1.4556923 -0.05156698
#[2,] -0.4252525 -0.64838966
#
#[[3]][[2]]
# [,1] [,2]
#[1,] 0.2450849 0.6129029
#[2,] -0.2372427 0.2555269

This time purrr:map_depth is your friend:
library(purrr)
map_depth(x, .depth = 2, 'a')
[[1]]
[[1]][[1]]
[,1] [,2]
[1,] 2.0693923 2.142611
[2,] 0.6840833 -1.440975
[[1]][[2]]
[,1] [,2]
[1,] 0.5415685 -0.7262725
[2,] -0.1604015 0.5218570
[[2]]
[[2]][[1]]
[,1] [,2]
[1,] 0.1245714 8.887078e-05
[2,] -0.2137517 -9.737122e-01
[[2]][[2]]
[,1] [,2]
[1,] 0.1993254 0.1116033
[2,] 0.5058125 -1.8523019
[[3]]
[[3]][[1]]
[,1] [,2]
[1,] 0.8661770 -1.76328811
[2,] -0.4559405 -0.08104821
[[3]][[2]]
[,1] [,2]
[1,] 0.7247404 -2.6736933
[2,] 0.8053027 0.5735254

You can use lapply as :
lapply(x, function(x) {
x1 <- unlist(x, recursive = FALSE)
do.call(rbind, x1[names(x1) == 'a'])
}) -> x1
x1
#[[1]]
# [,1] [,2]
#[1,] 0.3031708 0.09749503
#[2,] 0.9608749 0.51528005
#[3,] -0.6591001 0.09854767
#[4,] -1.6979551 -0.11709249
#[[2]]
# [,1] [,2]
#[1,] -1.11747169 -0.5668559
#[2,] -0.87458122 0.2517329
#[3,] -0.01483449 -1.7775506
#[4,] 1.57139735 -0.3488897
#[[3]]
# [,1] [,2]
#[1,] -0.2880580 -0.07233675
#[2,] 0.2933759 0.73729995
#[3,] 0.1070971 -0.27202774
#[4,] -0.5881883 -1.27391810
If you want everything combined into one you can do do.call(rbind, x1).

Related

simultaneous matrix operations in all list objects in R

I have a list of matrices in R as follows,
set.seed(1234)
data <- matrix(rnorm(3*4,mean=0,sd=1), 3, 4)
results <- lapply(1:ncol(data), function(i) outer(data[, i], data[, i]))
which results in:
[[1]]
[,1] [,2] [,3]
[1,] 1.4570077 -0.33487534 -1.3089918
[2,] -0.3348753 0.07696698 0.3008557
[3,] -1.3089918 0.30085569 1.1760127
[[2]]
[,1] [,2] [,3]
[1,] 5.502298 -1.0065968 -1.1870541
[2,] -1.006597 0.1841480 0.2171611
[3,] -1.187054 0.2171611 0.2560926
[[3]]
[,1] [,2] [,3]
[1,] 0.3303260 0.3141712 0.3244131
[2,] 0.3141712 0.2988064 0.3085474
[3,] 0.3244131 0.3085474 0.3186061
[[4]]
[,1] [,2] [,3]
[1,] 0.7921673 0.4247196 0.8886017
[2,] 0.4247196 0.2277129 0.4764227
[3,] 0.8886017 0.4764227 0.9967755
I want for each list object to sum the columns and find the minimum of these summation. For example min.results[[1]] = min(-0.186,0.042,0.167)=-0.186.
We may use sapply to loop over the list, get the column wise sum (colSums) and return with the minimum
sapply(results, \(x) min(colSums(x)))
-output
[1] -0.1868594 -0.7138005 0.9215250 1.1288552
Or using collapse
library(collapse)
fmin(dapply(results, colSums))
[1] -0.1868594 -0.7138005 0.9215250 1.1288552

How to extract lists within lists based on variable name in R

I have a list which I want to extract all sublists (matrices) with name a and store in a new list say matlist from the code below
x <- list()
x[[1]] <- list()
x[[2]] <- list()
x[[3]] <- list()
x[[1]]$a <- matrix(rnorm(4),2,2)
x[[1]]$b <- 3
x[[2]]$a <- matrix(rnorm(4),2,2)
x[[2]]$b <- 2
x[[3]]$a <- matrix(rnorm(4),2,2)
x[[3]]$b <- 1
Thank you in advance
You can use [[ in lapply with a to extract lists within lists based on variable name.
matlist <- lapply(x, "[[", "a")
matlist
#[[1]]
# [,1] [,2]
#[1,] 0.1232476 -0.2228539
#[2,] 0.4342695 -0.6379341
#
#[[2]]
# [,1] [,2]
#[1,] -0.4163436 -1.104486
#[2,] -2.3481197 1.523462
#
#[[3]]
# [,1] [,2]
#[1,] 0.1315805 -0.4286956
#[2,] -0.9083201 2.0258662
purrr::map is your friend:
library(purrr)
map(x, 'a')
[[1]]
[,1] [,2]
[1,] -0.9570164 -1.0893058
[2,] -1.5064699 0.5918877
[[2]]
[,1] [,2]
[1,] 0.5420939 1.5435010
[2,] -0.3326356 -0.1904059
[[3]]
[,1] [,2]
[1,] 1.892700 0.26731421
[2,] -1.735973 -0.08653999

using Map at depth to cbind columns in r

I am trying to cbind a column to a list within a list, without success. If list was of depth 1, the example would look as follows, where I would like to add dates to my example data frames in each list object:
ex_df_plain <- list(cbind(1,2),
cbind(3,4))
Map(cbind, as.list(c(2016, 2017)), ex_df_plain)
[[1]]
[,1] [,2] [,3]
[1,] 2016 1 2
[[2]]
[,1] [,2] [,3]
[1,] 2017 3 4
But as soon as I try to apply this to a list object where the depth of the list is greater than 1, the cbind reduces the list elements instead of combining:
at_depth_df <- list(as.list(c(1,2)), as.list(c(3,4)))
Map(cbind,
list(as.list(c(2015, 2016)), as.list(c(2017, 2018))),
at_depth_df)
[[1]]
[,1] [,2]
[1,] 2015 1
[2,] 2016 2
[[2]]
[,1] [,2]
[1,] 2017 3
[2,] 2018 4
My expected output should be
[[1]]
[[1]][[1]]
[,1] [,2]
[1,] 2015 1
[[1]][[2]]
[,1] [,2]
[1,] 2016 2
[[2]]
[[2]][[1]]
[,1] [,2]
[1,] 2017 3
[[2]][[2]]
[,1] [,2]
[1,] 2018 4
We need a recursive Map
Map(function(x, y) Map(cbind, x, y), lst1, at_depth_df)
where
lst1 <- list(as.list(c(2015, 2016)), as.list(c(2017, 2018)))
We can write a function to do this
f1 <- function(x, y, fun) {
if(is.atomic(x) && is.atomic(y)) {
x1 <- match.fun(fun)(x,y)
dimnames(x1) <- NULL
x1
} else {
Map(f1, x, y, MoreArgs = list(fun = fun))
}
}
f1(lst1, at_depth_df, cbind)
#[[1]]
#[[1]][[1]]
# [,1] [,2]
#[1,] 2015 1
#[[1]][[2]]
# [,1] [,2]
#[1,] 2016 2
#[[2]]
#[[2]][[1]]
# [,1] [,2]
#[1,] 2017 3
#[[2]][[2]]
# [,1] [,2]
#[1,] 2018 4

Extract matrices from a list of mixed data types

I have a list with the following form:
x = replicate(3, list(m = matrix(rnorm(16), 4, 4), s = rnorm(1)), simplify=FALSE)
x
#[[1]]
#[[1]]$m
# [,1] [,2] [,3] [,4]
#[1,] -0.412209 -0.50227 -2.62340 0.17549
#[2,] 1.344723 -1.52060 -0.59093 1.19701
#[3,] -0.016289 -0.88286 -0.33307 -0.48351
#[4,] 0.060760 0.32131 1.16896 -0.45940
#
#[[1]]$s
#[1] -1.3588
#
#
#[[2]]
#[[2]]$m
# [,1] [,2] [,3] [,4]
#[1,] -0.15345 -0.82106 0.93839 1.46115
#[2,] 1.60950 -2.35833 0.89621 0.35542
#[3,] -0.17792 0.54444 -0.17414 0.63614
#[4,] 0.85038 0.84373 0.24687 0.60172
#
#[[2]]$s
#[1] 3.6597
#
#
#[[3]]
#[[3]]$m
# [,1] [,2] [,3] [,4]
#[1,] 1.27724 0.19397 0.47393 -0.66518
#[2,] -0.75244 1.16476 1.74843 -1.03732
#[3,] 0.99433 -1.06129 0.15674 -0.83856
#[4,] 0.18471 1.30852 -0.38024 0.88538
#
#[[3]]$s
#[1] 0.49526
The goal is to get a list of matrices from the list above, and likewise a vector of scalars. How can this be done? Thanks!
You mean something like this...?
sapply(x, '[', 'm') # List of matrices
unlist(sapply(x, '[', 's')) # Vector of scalars

R Matrix Multiplication

I have a List, R=
[[1]]
[,1] [,2]
[1,] 100 0
[2,] 0 100
[[2]]
[,1] [,2]
[1,] 0.0006364031 0.2521204
[2,] 0.2521204236 99.9993643`
I'm suppose to do F %*% R
F
[1,] 1 -6.264917e-04
[2,] 1 1.575666e-04
As in F[1,] matrix multiplied with R[[1]], F[2,] matrix multiplied with R[[2]]
How should i go bout doing that?
Sorry. I think I was misunderstood. What I really want is F[1,]%*%R[[1]]%*%t(F[1,]) and F[2,]%*%R[[2]]%*%t(F[2,]) #Sven Hohenstein
mapply("%*%", as.data.frame(t(F)), R, SIMPLIFY = FALSE)
$V1
[,1] [,2]
[1,] 100 -0.06264917
$V2
[,1] [,2]
[1,] 0.0006761289 0.267877
Update
To answer your second question:
lapply(R, function(x) F %*% x %*% t(F))
[[1]]
[,1] [,2]
[1,] 100.00004 99.99999
[2,] 99.99999 100.00000
[[2]]
[,1] [,2]
[1,] 0.0003597493 0.0005083061
[2,] 0.0005083062 0.0007183373
Update
To answer your updated question:
mapply(function(x, y) y %*% x %*% as.matrix(y), R, as.data.frame(t(F)),
SIMPLIFY = FALSE)
[[1]]
[,1]
[1,] 100
[[2]]
[,1]
[1,] 0.0007183373
R <- list(matrix(c(100,0,0,100), 2), matrix(c(0.0006364031,0.2521204236,0.2521204,99.9993643), 2))
F <- matrix(c(1, 1, -6.264917e-04, 1.575666e-04), 2)
lapply(1:2, function(x) F[x,] %*% R[[x]])
## [[1]]
## [,1] [,2]
## [1,] 100 -0.06264917
##
## [[2]]
## [,1] [,2]
## [1,] 0.0006761289 0.267877
Just by doing it:
> F[1,]%*%R[[1]]
[,1] [,2]
[1,] 100 -0.06264917
> F[2,]%*%R[[2]]
[,1] [,2]
[1,] 0.0006761289 0.267877
Was there some particular way you wanted those stored?

Resources