【问题标题】:Moving objects of a list to another list将列表的对象移动到另一个列表
【发布时间】:2020-01-12 01:33:45
【问题描述】:

我有由mice 库创建的mids 对象列表,如下所示:

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
)

# 1. Split df into smaller df
df_iso <- split(df, df$iso) # Creates a list of dataframes

# 2. Impute smaller df, creates a list with mids
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")})
}

我希望能够简单地将列表 df_iso_1df_iso_2mids 对象移动到另一个列表,该列表具有 ISO 代码的名称(这导致列表 mids具有相同 iso 代码的对象,而不是具有所有 iso 代码的列表)。我尝试了以下方法:

NLD = list()
AUS = list()
ECU = list()
BRA = list()

for (n in 1:length(df_iso_1)){
  if (df_iso_1[[i]]["data"]==NLD) {
  NLD[[i]] <- 
    df_iso_1[[i]] }
}

然而这给出了错误:

Error in Ops.data.frame(df_iso_1[[i]], NLD) : 
  list of length 21 not meaningful

关于如何正确执行此操作的任何建议?

编辑:使用科尔的回答,我想我想实现以下目标:

names(df_iso_1) <- names(df_iso)
names(df_iso_2) <- names(df_iso)
for (n in 1:2) {
  x <- get(paste0("df_iso_", n))
  NLD[[n]] <- x[['NLD']]
}

由于某种原因,这只会将一项添加到 NLD 列表中。

【问题讨论】:

    标签: r list for-loop data.table r-mice


    【解决方案1】:

    你想要:

    names(df_iso_1) <- names(df_iso)
    NLD[[1]] <- df_iso_1[['NLD']]
    

    我们需要克服df_iso_1 没有任何名称可以作为子集的原因。另一种方法是嵌套lapply 语句并循环通过df_iso 和我们想要的任何种子。

    seeds = c(1,2)
    df_iso_all <- lapply(df_iso,
                         function(ISO) lapply(seeds,
                                              function(seed) mice(ISO, m=1, maxit = 5, seed = seed)
                                              )
                         )
    
    df_iso_all[['NLD']]
    

    我们还可以使用by() 函数将splitlapply 包含在一行中。

    #or split using by an do it at once:
    by(data = df, INDICES = df$iso,
       FUN = function(ISO) lapply(seeds, function(seed) mice(ISO, m = 1, maxit = 5, seed = seed)))
    

    您甚至可以提前在数据处理中包含一些错误处理,以便只有 1,000 个isos。

    df[, GRPING := .GRP, by = iso]
    by(data = df[GRPING < 1000, !c('GRPING')],
       ...,
       ...)
    

    以下是在我的计算机上运行的代码的复制和粘贴:

    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
    )
    
    # 1. Split df into smaller df
    df_iso <- split(df, df$iso) # Creates a list of dataframes
    
    # 2. Impute smaller df, creates a list with mids
    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")})
    }
    
    NLD = list()
    AUS = list()
    ECU = list()
    BRA = list()
    
    names(df_iso_1) <- names(df_iso)
    names(df_iso_2) <- names(df_iso)
    
    for (n in 1:2) {
      x <- get(paste0("df_iso_", n))
      NLD[[n]] <- x[['NLD']]
      AUS[[n]] <- x[['AUS']]
      ECU[[n]] <- x[['ECU']]
      BRA[[n]] <- x[['BRA']]
    }
    
    NLD
    AUS
    ECU
    BRA
    

    【讨论】:

    • 非常感谢您的回答!这是一个巨大的帮助。有没有办法将结果上移 1 级?现在的结果是[[1]]下面有[NLD],但是我需要[NLD]关卡消失,信息直接在[[1]]下面。那可能吗?有没有办法用for循环来做到这一点?
    • 查看编辑。更改只是双括号:df_iso_all[['NLD']]。出于好奇,为什么您更喜欢单独保存所有对象而不是一个列表?
    • 非常感谢科尔!我快到了,我只是无法正确使用 for 循环(请参阅编辑)。我最初是这样安排的,以在进行插补时节省内存。现在我必须把它放回这个结构中,以使mice 能够汇集插补。事后看来,我认为有更好的选择..
    • @Tom,你的代码对我有用。我复制并粘贴了我的所有代码。每个iso 是2 个列表。
    • 当我复制您的代码时,它也以某种方式对我有用。也许我在自己的代码中错误地忽略了。无论如何,非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    相关资源
    最近更新 更多