【问题标题】:Names of nested list containing dots (e.g. "c.2)包含点的嵌套列表的名称(例如“c.2”)
【发布时间】:2021-10-20 00:59:44
【问题描述】:

如何获取嵌套列表(包含数据框)的叶子名称

p <- list(a=1,b=list(b1=2,b2=3),c=list(c1=list(c11='a',c12='x'),c.2=data.frame("t"=1)))

转成矢量格式:

[[1]]
[1] "a"
[[2]]
[1] "b" "b1"
[[3]]
[1] "b" "b2"
[[4]]
[1] "c" "c1" "c11"
[[5]]
[1] "c" "c1" "c12"
[[6]]
[1] "c" "c.2"

问题是我的列表包含带点的名称(例如“c.2”)。通过使用 unlist,可以得到 "c.c.2",而我(或者可能是 strsplit)无法判断该点是 unlist 的分隔符还是名称的一部分。这就是与this question 的区别。

它应该忽略 data.frames。到目前为止,我的方法改编自 here,但与 unlist 创建的点相矛盾:

listNames = function(l, maxDepth = 2) {
  n = 0
  listNames_rec = function(l, n) {
    if(!is.list(l) | is.data.frame(l) | n>=maxDepth) TRUE
    else { 
      n = n + 1
      # print(n)
      lapply(l, listNames_rec, n)
    }
  }
  n = names(unlist(listNames_rec(l, n)))
  return(n)
}
listNames(p, maxDepth = 3)
[1] "a"        "b.b1"     "b.b2"     "c.c1.c11" "c.c1.c12" "c.c.2"  

【问题讨论】:

  • 我不是把它作为重复的here 关闭了吗?您是否尝试过链接中的解决方案?
  • 嗨@Sotos,是的,你关闭了它,但我的观点是关于未列出的点(哈哈)。我改变了我的问题以更多地解决这个问题,请参阅粗体中间部分。
  • strsplit() 不起作用吗?即... n = strsplit(names(unlist(listNames_rec(l, n))), '\\.')
  • 不,这给出了"c" "c" "2",但应该是"c" "c.2"。这就是重点

标签: r list


【解决方案1】:

一种方法可能是:

listNames = function(l, n, N) {
  if(!is.list(l) | is.data.frame(l) | n<1) list(rev(N))
  else unlist(Map(listNames, l, n=n-1, N=lapply(names(l), c, N)), FALSE, FALSE)
}

listNames(p, 3, NULL)
#[[1]]
#[1] "a"
#
#[[2]]
#[1] "b"  "b1"
#
#[[3]]
#[1] "b"  "b2"
#
#[[4]]
#[1] "c"   "c1"  "c11"
#
#[[5]]
#[1] "c"   "c1"  "c12"
#
#[[6]]
#[1] "c"   "c.2"

【讨论】:

    【解决方案2】:

    不是一个完整的答案,但我想 rrapply package 可以在这里帮助你吗? 一种选择是提取所有名称:

    library(rrapply)
    library(dplyr)
    rrapply(p, how = "melt") %>% 
      select(-value)
    #   L1   L2   L3
    # 1  a <NA> <NA>
    # 2  b   b1 <NA>
    # 3  b   b2 <NA>
    # 4  c   c1  c11
    # 5  c   c1  c12
    # 6  c  c.2    t
    

    这里的问题是 data.frame 名称也包含在上面,因此您可以单独提取它们:

    #extract data frame name
    rrapply(p, classes = "data.frame", how = "melt") %>% 
      select(-value)
    #   L1  L2
    # 1  c c.2
    

    然后您可以使用这两个数据集并可能提取重复项但保留数据框名称

    rrapply(p, how = "melt") %>%  
      bind_rows(rrapply(p, classes = "data.frame", how = "melt")) 
      #then filter etc...
    

    【讨论】:

      【解决方案3】:

      像这样?

      subnames <- function(L, s) {
        if (!is.list(L) || is.data.frame(L)) return(L)
        names(L) <- gsub(".", s, names(L), fixed = TRUE)
        lapply(L, subnames, s)
      }
      
      res <- listNames(subnames(p, ":"), maxDepth = 3)
      gsub(":", ".",
        gsub(".", "$", res, fixed = TRUE),
        fixed = TRUE
      )
      #[1] "a"        "b$b1"     "b$b2"     "c$c1$c11" "c$c1$c12" "c$c.2" 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-10
        • 2018-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多