【问题标题】:Looping through a sub list, where the "sub sub" list stays constant循环遍历子列表,其中“子子”列表保持不变
【发布时间】:2020-01-15 03:16:38
【问题描述】:

我想遍历一个子列表,其中“子子”列表保持不变。我提到的所有代码都只是可重现的示例(请注意实际数据非常大)并且应该可以正常工作。

我有一个列表列表,每个列表都有 2 个子列表,如下所示:

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)

现在new_nested$AUS$a 访问子列表AUS 的列表a。到目前为止一切顺利。

我想将下面的两个列表 (df_iso_1, df_iso_2) 重新分配到我刚刚创建的列表结构中。

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)

虽然new_nested$AUS$a 访问列表,但我想循环使用索引而不是通过名称引用它们的iso 代码:

for (n in length(df_iso)) {
new_nested$[i]$a <- df_iso_1[n]
}

但这不起作用。遍历这些列表的正确语法是什么?

期望的输出:

df_iso_1df_iso_2 开始,mids 对象按iso 代码池化。换句话说,所有iso 代码都放在了新结构中:

所以new_nested 的列表NLD 填充了来自df_iso_1df_iso_2 的NLD mids 对象,其列表列表AUS 填充了来自df_iso_1 的AUS mids 对象和df_iso_2.

【问题讨论】:

    标签: r list for-loop lapply


    【解决方案1】:

    这里有两种方法。第一个是用seq_len(length(df_iso)) 修复你的循环并匹配你的输出,将你的df_iso_1[n] 更改为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
    

    第二种方法是使用mapply 循环遍历df_iso_n 列表的每个元素,将它们组合成一个新的列表矩阵:

    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
    

    此外,考虑重构代码仍然是一个好主意。这主要通过 3 行完成所有操作:

    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]]
    ...
    

    【讨论】:

    • 非常感谢科尔!这非常有帮助。如果我需要重新运行它,我将使用最后一个选项。然而,它需要将近三周的时间才能运行。
    • 这很公平。请注意,使用by 可以让您更轻松地使用并行计算。使用library(future.apply)future_by,我将时间从 200 毫秒减少到 140 毫秒,仅使用了一个 2 核处理器。
    猜你喜欢
    • 1970-01-01
    • 2012-07-08
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    相关资源
    最近更新 更多