如何在不丢失结构的情况下将 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 
    
  }
}