Reputation: 2341
I would like to loop through a sub list, where the "sub sub" list stays constant. All code mentioned by me is just the reproducible example (please note that the actual data is really large) and should work without issue.
I have a list of lists which each have 2 sub lists as follows:
library(data.table)
library(mice)
df <- fread(
"A B C D E F iso year
0 A NA 1 NA NA NLD 2009
1 Y NA 2 NA NA NLD 2009
0 Q NA 3 NA NA AUS 2011
1 NA NA 4 NA NA AUS 2011
0 0 NA 7 NA NA NLD 2008
1 1 NA 1 NA NA NLD 2008
0 1 NA 3 NA NA AUS 2012
0 NA 1 NA 1 NA ECU 2009
1 NA 0 NA 2 0 ECU 2009
0 NA 0 NA 3 0 BRA 2011
1 NA 0 NA 4 0 BRA 2011
0 NA 1 NA 7 NA ECU 2008
1 NA 0 NA 1 0 ECU 2008
0 NA 0 NA 3 2 BRA 2012
1 NA 0 NA 4 NA BRA 2012",
header = TRUE
)
# Creates a list
df_iso <- split(df, df$iso) # Creates a list of dataframes
# Creates a list of lists
mylist.names <- names(df_iso)
df_iso_list <- vector("list", length(mylist.names))
names(df_iso_list) <- mylist.names
f <- function(x) return(list(a = list(), b = list()))
new_nested <- lapply(df_iso, f)
Now new_nested$AUS$a
accesses the list a
of sub list AUS
. So far so good.
I would like to redistribute the two lists (df_iso_1, df_iso_2
) below to the list structure I just created.
df_iso_1 = list()
for (i in 1:length(df_iso)) {
tryCatch({
df_iso_1 [[i]] <- mice(df_iso[[i]], m=1, maxit = 5, seed=1)
if (i==1000) stop("stop")
}, error=function(e){cat("ERROR :",conditionMessage(e), "\n")})
}
df_iso_2 = list()
for (i in 1:length(df_iso)) {
tryCatch({
df_iso_2 [[i]] <- mice(df_iso[[i]], m=1, maxit = 5, seed=2)
if (i==1000) stop("stop")
}, error=function(e){cat("ERROR :",conditionMessage(e), "\n")})
}
names(df_iso_1) <- names(df_iso)
names(df_iso_2) <- names(df_iso)
Although new_nested$AUS$a
accesses the list, I would like to loop through the iso
codes with an index instead of referring to them by name:
for (n in length(df_iso)) {
new_nested$[i]$a <- df_iso_1[n]
}
This does however not work. What is the correct syntax of looping through these lists?
Desired output:
From df_iso_1
and df_iso_2
, the mids
objects are pooled per iso
code. In other words, all iso
codes are put together in the new structure:
So new_nested
has its list NLD
filled with the NLD mids
objects from df_iso_1
and df_iso_2
, and its list list AUS
filled with the AUS mids
objects from df_iso_1
and df_iso_2
.
Upvotes: 2
Views: 97
Reputation: 11255
Here are two approaches. The first is to fix your loop with seq_len(length(df_iso))
and to match your output, changing your df_iso_1[n]
to df_iso1[[n]]
:
for (n in seq_len(length(df_iso))) {
new_nested[[names(df_iso)[n]]]$a <- df_iso_1[[n]]
new_nested[[names(df_iso)[n]]]$b <- df_iso_2[[n]]
}
new_nested$AUS$a
Class: mids
Number of multiple imputations: 1
Imputation methods:
A B C D E F iso year
"" "" "" "" "" "" "" ""
PredictorMatrix:
A B C D E F iso year
A 0 0 0 0 0 0 0 1
B 0 0 0 0 0 0 0 0
C 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 1
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
Number of logged events: 6
it im dep meth out
1 0 0 constant B
2 0 0 constant C
3 0 0 constant E
4 0 0 constant F
5 0 0 constant iso
6 0 0 collinear D
The second approach is to use mapply
to loop through each element of your df_iso_n
lists to combine them into a new matrix of lists:
mapply(list, df_iso_1, df_iso_2)
# AUS BRA ECU NLD
#[1,] List,21 List,21 List,21 List,21
#[2,] List,21 List,21 List,21 List,21
mapply(list, df_iso_1, df_iso_2)[, 'AUS']
[[1]]
Class: mids
Number of multiple imputations: 1
Imputation methods:
A B C D E F iso year
"" "" "" "" "" "" "" ""
PredictorMatrix:
A B C D E F iso year
A 0 0 0 0 0 0 0 1
B 0 0 0 0 0 0 0 0
C 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 1
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
Number of logged events: 6
it im dep meth out
1 0 0 constant B
2 0 0 constant C
3 0 0 constant E
4 0 0 constant F
5 0 0 constant iso
6 0 0 collinear D
[[2]]
Class: mids
Number of multiple imputations: 1
Imputation methods:
A B C D E F iso year
"" "" "" "" "" "" "" ""
PredictorMatrix:
A B C D E F iso year
A 0 0 0 0 0 0 0 1
B 0 0 0 0 0 0 0 0
C 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 1
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
Number of logged events: 6
it im dep meth out
1 0 0 constant B
2 0 0 constant C
3 0 0 constant E
4 0 0 constant F
5 0 0 constant iso
6 0 0 collinear D
Also, it still would be a good idea to consider refactoring your code. This largely does everything in 3 lines:
seeds = c(1,2)
by(data = df, INDICES = df$iso,
FUN = function(ISO) lapply(seeds, function(seed) mice(ISO, m = 1, maxit = 5, seed = seed)))
df$iso: AUS
[[1]]
Class: mids
Number of multiple imputations: 1
Imputation methods:
A B C D E F iso year
"" "" "" "" "" "" "" ""
PredictorMatrix:
A B C D E F iso year
A 0 0 0 0 0 0 0 1
B 0 0 0 0 0 0 0 0
C 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 1
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
Number of logged events: 6
it im dep meth out
1 0 0 constant B
2 0 0 constant C
3 0 0 constant E
4 0 0 constant F
5 0 0 constant iso
6 0 0 collinear D
[[2]]
Class: mids
Number of multiple imputations: 1
Imputation methods:
A B C D E F iso year
"" "" "" "" "" "" "" ""
PredictorMatrix:
A B C D E F iso year
A 0 0 0 0 0 0 0 1
B 0 0 0 0 0 0 0 0
C 0 0 0 0 0 0 0 0
D 1 0 0 0 0 0 0 1
E 0 0 0 0 0 0 0 0
F 0 0 0 0 0 0 0 0
Number of logged events: 6
it im dep meth out
1 0 0 constant B
2 0 0 constant C
3 0 0 constant E
4 0 0 constant F
5 0 0 constant iso
6 0 0 collinear D
----------------------------------------------------
df$iso: BRA
[[1]]
...
Upvotes: 1