【问题标题】:Filter list in R base on criteria within list objects根据列表对象中的条件过滤R中的列表
【发布时间】:2019-12-21 23:49:15
【问题描述】:

这是一个微不足道的问题,但我很难过。如何根据数据框的长度过滤数据框列表?该列表是嵌套的——这意味着有不同长度的数据帧列表的列表。这是一个例子。我想过滤或子集列表以仅包含长度为 n 的对象,例如 3。

这是一个例子和我目前的方法。

library(tidyverse)

# list of list with arbitrary lengths 

star.wars_ls <- list(starwars[1:5], 
                     list(starwars[1:8], starwars[4:6]), 
                     starwars[1:2], 
                     list(starwars[1:7], starwars[2:6]), 
                     starwars[1:3])


# I want to filter the list by dataframes that are 3 variables long (i.e. length(df == 3).

# Here is my attempt, I'm stuck at how to obtain 
# the number of varibles in each dataframe and then filter by it. 

map(star.wars_ls, function(x){
    map(x, function(x){ ## Incorrectly returns 20 for all 
        length(y)
    })

})

【问题讨论】:

  • 你想对嵌套做什么?松散?忽视?分层应用过滤器?
  • 我想在适用时保留嵌套。所以我想最好分层应用过滤器。
  • 我现在将对其进行编辑。谢谢。
  • 嗯,我认为“递归过滤”可能比“分层过滤”更好。 This looks promising
  • 我认为您还需要编辑以 (a) 定义 n 和 (b) 定义 y。很高兴看到预期的结果。比如,如果n 是3,你想要list(NULL, list(NULL, starwars[4:6]), list(NULL, NULL), starwars[1:3]) 吗?还是别的什么?

标签: r list filter tidyverse


【解决方案1】:

我们可以的

  map(star.wars_ls, ~ if(is.data.frame(.x)) .x[length(.x) == 3] else map(.x, ~ .x[length(.x) == 3]))

【讨论】:

    【解决方案2】:

    您应该能够检查star.wars_ls 中的项目是列表还是数据框。然后,检查每个项目中的列数。尝试使用:

    library(tidyverse)
    
    # list of list with arbitrary lengths 
    
    star.wars_ls <- list(starwars[1:5], 
                         list(starwars[1:8], starwars[4:6]), 
                         starwars[1:2], 
                         list(starwars[1:7], starwars[2:6]), 
                         starwars[1:3])
    
    
    # I want to filter the list by dataframes that are 3 variables long (i.e. length(df == 3).
    
    datacols <- map(star.wars_ls, function(X) {
      if (is.data.frame(X) == T) {
        ncol(X) } 
        else {
          map(X, function(Y) {
            ncol(Y)
          })
          }
        }
    )
    
    # > datacols
    # [[1]]
    # [1] 5
    # 
    # [[2]]
    # [[2]][[1]]
    # [1] 8
    # 
    # [[2]][[2]]
    # [1] 3
    # 
    # 
    # [[3]]
    # [1] 2
    # 
    # [[4]]
    # [[4]][[1]]
    # [1] 7
    # 
    # [[4]][[2]]
    # [1] 5
    # 
    # 
    # [[5]]
    # [1] 3
    

    这只会为您提供列表中每个数据框的长度(列数)。获取索引(我确信有一种更有效的方法可以做到这一点——也许其他人可以提供帮助):

    indexlist <- c()
    for (i in 1:length(datacols)) {
      if (length(datacols[[i]]) == 1) {
        if (datacols[[i]][1] == 3) {
          index <- i 
          indexlist <- c(indexlist, as.character(index))
        }
      } else {
        for (j in 1:length(datacols[[i]])) {
          if (datacols[[i]][[j]][1] == 3) {
            index <- str_c(i, ",", j)
            indexlist <- c(indexlist, index)
          }
        }
      }
    }
    
    # > indexlist
    # [1] "2,2" "5"  
    

    【讨论】:

      【解决方案3】:

      你可以使用递归。列表嵌套的深度无关紧要:

      ff = function(x)map(x,~if(is.data.frame(.x)){if(length(.x)==3) .x} else ff(.x))
      ff(star.wars_ls)
      

      【讨论】:

        猜你喜欢
        • 2017-10-18
        • 1970-01-01
        • 2021-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-10
        • 2022-10-07
        相关资源
        最近更新 更多