如何在不丢失结构的情况下将 NESTED 列表强制为 double (R)
How to coerce NESTED list into double without losing the structure (R)
似乎有很多关于如何将列表转换为双精度数的问题得到解答,但似乎没有任何东西可以使列表的结构保持有效。
我有一个这样的嵌套列表(R 输出):
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
然后我将此列表传递给 JAGS 以迭代其元素。在 JAGS 循环中,我想迭代第一个、第二个和第三个元素,然后检索存储在其中的数字,以便在另一个循环中再次迭代。
这意味着我想访问第一个元素的“1 3 4 8 11 13 17”等等。
我用来迭代的JAGS脚本中的代码是这样的:
for (j in 1:subjects) { # Subject-loop
for (i in my_list[j]) { # Trial loop
....
}
}
这样做的背景是并非所有受试者都有有效的试验。
所以我需要通过 JAGS 对每个主题的有效试验。
我打算用上面的嵌套列表来做到这一点。然而,事实证明 JAGS 无法处理列表 - 所以现在我尝试将其转换为 JAGS 可以迭代的东西,而不会丢失哪些试验属于哪个主题的信息。
我需要保持结构正常运行,这样所有只是将列表转换为单个向量的东西都无济于事,因为我无法再对其进行迭代。
有什么建议吗?我试图只通过列表,但 JAGS 无法处理它并且需要一个“双”。我也试过把它转换成矩阵,但没能保持结构。
谢谢!
更新:我试过了,它有点像矩阵似乎与 JAGS 一起工作
list_as_matrix <- do.call(rbind, my_list)
但是嵌套列表的长度不同,所以矩阵中的空列只是一遍又一遍地填充相同的值。
JAGS 错误代码为:
4 nodes produced errors; first error: 'list' object cannot be coerced to type "double"
由于 DaveArmstrong 的输入,更新了答案:
# 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))
}
}
}
您可以 map 列出其中 returns 任意函数应用于每个列表成员后的初始列表(如果需要,也可以递归)。在 base R 中,您可以使用 lapply()
或 Map()
来执行此操作。包裹{purrr} extends this concept with a variety of convenient functions.
示例:
## base R
lapply(your_list, function(list_element) {some_JAGS_call(list_element)})
## purrr (plus pipe and formula notation)
your_list %>% map(~ some_JAGS_call(.x))
This online ressource R 和 JAGS 可能会有帮助。
编辑 1
例如,如果您需要将 my_list 从向量列表映射到适合 JAGS 的矩阵列表,您 lapply
(list-apply)函数 as.matrix()
:
my_list_of_matrices <- lapply(my_list, function(el) as.matrix(el))
(根据 JAGS 调用的要求向 as.matrix()
提供更多参数。)
编辑 2
陷阱:当您在循环中使用单括号索引列表时:
for (i in my_list[j]) { # Trial loop
您仍将获得列表元素作为列表。使用双括号:
for (i in my_list[[j]])
选择没有粘性列表部分的列表元素(例如矩阵,如果是的话)。
像这样的事情怎么样:
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))
将您的列表变成一个用 NA
个值填充的矩阵。
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
然后,对于每个主题,确定具有有效数据的第一列和最后一列。
minvals <- 1
maxvals <- apply(mat, 1, function(x)max(which(!is.na(x))))
然后,在您的 JAGS 模型中,您可以从 mat
中提取适当的值来识别试验编号。
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
}
}
似乎有很多关于如何将列表转换为双精度数的问题得到解答,但似乎没有任何东西可以使列表的结构保持有效。
我有一个这样的嵌套列表(R 输出):
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
然后我将此列表传递给 JAGS 以迭代其元素。在 JAGS 循环中,我想迭代第一个、第二个和第三个元素,然后检索存储在其中的数字,以便在另一个循环中再次迭代。 这意味着我想访问第一个元素的“1 3 4 8 11 13 17”等等。
我用来迭代的JAGS脚本中的代码是这样的:
for (j in 1:subjects) { # Subject-loop
for (i in my_list[j]) { # Trial loop
....
}
}
这样做的背景是并非所有受试者都有有效的试验。 所以我需要通过 JAGS 对每个主题的有效试验。
我打算用上面的嵌套列表来做到这一点。然而,事实证明 JAGS 无法处理列表 - 所以现在我尝试将其转换为 JAGS 可以迭代的东西,而不会丢失哪些试验属于哪个主题的信息。
我需要保持结构正常运行,这样所有只是将列表转换为单个向量的东西都无济于事,因为我无法再对其进行迭代。
有什么建议吗?我试图只通过列表,但 JAGS 无法处理它并且需要一个“双”。我也试过把它转换成矩阵,但没能保持结构。
谢谢!
更新:我试过了,它有点像矩阵似乎与 JAGS 一起工作
list_as_matrix <- do.call(rbind, my_list)
但是嵌套列表的长度不同,所以矩阵中的空列只是一遍又一遍地填充相同的值。
JAGS 错误代码为:
4 nodes produced errors; first error: 'list' object cannot be coerced to type "double"
由于 DaveArmstrong 的输入,更新了答案:
# 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))
}
}
}
您可以 map 列出其中 returns 任意函数应用于每个列表成员后的初始列表(如果需要,也可以递归)。在 base R 中,您可以使用 lapply()
或 Map()
来执行此操作。包裹{purrr} extends this concept with a variety of convenient functions.
示例:
## base R
lapply(your_list, function(list_element) {some_JAGS_call(list_element)})
## purrr (plus pipe and formula notation)
your_list %>% map(~ some_JAGS_call(.x))
This online ressource R 和 JAGS 可能会有帮助。
编辑 1
例如,如果您需要将 my_list 从向量列表映射到适合 JAGS 的矩阵列表,您 lapply
(list-apply)函数 as.matrix()
:
my_list_of_matrices <- lapply(my_list, function(el) as.matrix(el))
(根据 JAGS 调用的要求向 as.matrix()
提供更多参数。)
编辑 2
陷阱:当您在循环中使用单括号索引列表时:
for (i in my_list[j]) { # Trial loop
您仍将获得列表元素作为列表。使用双括号:
for (i in my_list[[j]])
选择没有粘性列表部分的列表元素(例如矩阵,如果是的话)。
像这样的事情怎么样:
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))
将您的列表变成一个用 NA
个值填充的矩阵。
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
然后,对于每个主题,确定具有有效数据的第一列和最后一列。
minvals <- 1
maxvals <- apply(mat, 1, function(x)max(which(!is.na(x))))
然后,在您的 JAGS 模型中,您可以从 mat
中提取适当的值来识别试验编号。
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
}
}