【问题标题】:Extract data frames from nested list从嵌套列表中提取数据框
【发布时间】:2021-12-28 21:45:11
【问题描述】:

我有一个嵌套的列表列表,其中包含一些数据框。但是,数据框可以出现在列表中的任何级别。我想要结束的是一个平面列表,即只有一个级别,其中每个元素只有数据框,而所有其他东西都被丢弃了。

我为此想出了一个解决方案,但它看起来很笨拙,我相信应该有一个更优雅的解决方案。

重要的是,我正在寻找基础 R 中的东西,它可以在嵌套列表中的任何级别提取数据帧。我尝试过unlist() 并涉足rapply(),但不知何故没有找到令人满意的解决方案。

示例代码如下:示例列表、我实际想要实现的目标以及我自己不太满意的解决方案。感谢您的帮助!

# extract dfs from list

# example of multi-level list with some dfs in it
# note, dfs could be nested at any level
problem1 <- list(x1 = 1,
              x2 = list(
                x3 = "dog",
                x4 = data.frame(cats = c(1, 2),
                               pigs = c(3, 4))
              ),
              x5 = data.frame(sheep = c(1,2,3),
                             goats = c(4,5,6)),
              x6 = list(a = 2,
                       b = "c"),
              x7 = head(cars,5))

# want to end up with flat list like this (names format is optional)
result1 <- list(x2.x4 = data.frame(cats = c(1, 2),
                                   pigs = c(3, 4)),
                x5 = data.frame(sheep = c(1,2,3),
                                goats = c(4,5,6)),
                x7 = head(cars,5))

# my solution (not very satisfactory)

exit_loop <- FALSE
while(exit_loop == FALSE){
  # find dfs (logical)
  idfs <- sapply(problem1, is.data.frame)
  # check if all data frames
  exit_loop <- all(idfs)
  # remove anything not df or list
  problem1 <- problem1[idfs | sapply(problem1, is.list)]
  # find dfs again (logical)
  idfs <- sapply(problem1, is.data.frame)
  # unlist only the non-df part
  problem1 <- c(problem1[idfs], unlist(problem1[!idfs], recursive = FALSE))

}

【问题讨论】:

    标签: r


    【解决方案1】:

    也许考虑一个像这样的简单递归函数

    find_df <- function(x) {
      if (is.data.frame(x))
        return(list(x))
      if (!is.list(x))
        return(NULL)
      unlist(lapply(x, find_df), FALSE)
    }
    

    结果

    > find_df(problem1)
    $x2.x4
      cats pigs
    1    1    3
    2    2    4
    
    $x5
      sheep goats
    1     1     4
    2     2     5
    3     3     6
    
    $x7
      speed dist
    1     4    2
    2     4   10
    3     7    4
    4     7   22
    5     8   16
    

    【讨论】:

    • 谢谢,这正是我想要的!
    【解决方案2】:

    有一个函数叫做rrapply 你可以使用它。唯一的缺点是我没有得到所需的名称:

    rrapply::rrapply(problem1, is.data.frame, classes = 'data.frame', how = 'flatten')
    
    $x4
      cats pigs
    1    1    3
    2    2    4
    
    $x5
      sheep goats
    1     1     4
    2     2     5
    3     3     6
    
    $x7
      speed dist
    1     4    2
    2     4   10
    3     7    4
    4     7   22
    5     8   16
    

    【讨论】:

    • 如果需要父节点名称,rrapply(problem1, classes = "data.frame", how = "melt") 将 data.frames 展平为一个列表,并且还包括每个单独层的父节点名称
    • 谢谢,这也是一个不错的解决方案,虽然除了在我的情况下,我正在寻找基本 R 中的东西。但仍然很高兴知道!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2021-06-17
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多