there seem to many answered questions about how to convert a list into a double, but nothing that seems to keep the structure of the list valid.
I have a nested list like that (R output):
my_list
[[1]]
[1] 1 3 4 8 11 13 17
[[2]]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
[[3]]
[1] 2 14
Then I pass this list to JAGS in order to iterate over its elements. In the JAGS loop I want to iterate over the first, second and third element and then retrieve the numbers stored in there to be iterated over again in another loop. That means I want to access "1 3 4 8 11 13 17" of the first element and so on.
The code in the JAGS script that I use to iterate is like this:
for (j in 1:subjects) { # Subject-loop
for (i in my_list[j]) { # Trial loop
....
}
}
The background for this is that not all subjects have valid trials. so I need to pass JAGS the valid trials for each subject.
I intended to do that with a nested list like above. However, it turns out JAGS cannot deal with list - so now I try to convert it into something that JAGS can iterate over without losing the information which trials belong to which subject.
I need to keep the structure functioning so everything that just converts the list into a single vector does not help as I cannot iterate over that anymore.
Any suggestions? I have tried to just pass the list, but JAGS cannot deal with that and needs a "double". I also tried to convert it into a matrix, but failed to keep structure.
Thank you!
Update: I tried this, which works somewhat as matrixes seem to work with JAGS
list_as_matrix <- do.call(rbind, my_list)
But the nested lists have different lengths, so the empty columns in the matrix are just filled with the same values over an over again.
The JAGS error code is:
4 nodes produced errors; first error: 'list' object cannot be coerced to type "double"
# a list of 6 subjects and their valid trials
subjects_and_their_valid_trials <- list(
c(1,3,4,8, 11,13,17),
c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20),
c(2, 14),
c(1,3,4,8, 11,13,17),
c(1,2,3,4,5,6,8,9,10,11,12,13,14,15,17,18,19,20),
c(6, 12))
l <- subjects_and_their_valid_trials # make it easier to read
maxlen <- max(sapply(l, length))
mat <- t(sapply(l, function(x)c(x, rep(NA, maxlen-length(x)))))
minvals <- 1
maxvals <- apply(mat, 1, function(x)max(which(!is.na(x))))
# ---- How the JAGS Loop is structured
nSubj_Condition1 <- 6
# Loop for condition
for (j in 1:nSubj_Condition1) { #Subject-loop
print( "///---------------------------------- ///")
print(paste("Subject number", j))
#-------------------------
# This loop restricts the following loop to valid cases in the matrix
for (k in 1:maxvals[j]) {
print(paste("Iterating through trial matrix... step", k))
# This loop loops through the matrix of valid trials for each subjects
for (i in mat[j,k]) {
print(paste("A valid trial number is:", i))
}
}
}
What about something like this:
l <- list(
c(1,3,4,8, 11,13,17),
c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20),
c(2, 14))
Turn your list into a matrix that is padded out with NA
values.
maxlen <- max(sapply(l, length))
mat <- t(sapply(l, function(x)c(x, rep(NA, maxlen-length(x)))))
# > mat
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16]
# [1,] 1 3 4 8 11 13 17 NA NA NA NA NA NA NA NA NA
# [2,] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# [3,] 2 14 NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# [,17] [,18] [,19] [,20]
# [1,] NA NA NA NA
# [2,] 17 18 19 20
# [3,] NA NA NA NA
Then, for each subject, identify the first and last columns with valid data.
minvals <- 1
maxvals <- apply(mat, 1, function(x)max(which(!is.na(x))))
Then, in your JAGS model, you could pull the appropriate values out of mat
to identify the trial numbers.
for (j in 1:subjects) { # Subject-loop
for (i in minvals[j]:maxvals[j]) { # Trial loop
mat[j,i] ## gives you the trial number for each subject
}
}