【问题标题】:Preserving nested element names while combining elements of list of lists with the same name在组合具有相同名称的列表列表的元素时保留嵌套元素名称
【发布时间】:2020-07-08 02:22:30
【问题描述】:

我有一个如下列表。

dlist <- list(a = list(a1 = list(k = 25, m = 34)),
              b = list(b1 = list(k = 23, m = 58)),
              c = list(c1 = list(k = NA, m = 32)),
              a = list(a2 = list(k = 42, m = 35)),
              c = list(c2 = list(k = 41, m = 87)),
              d = list(d1 = list(k = 48, m = 90)),
              b = list(b2 = list(k = 85, m = 98)),
              b = list(b3 = list(k = 47, m = 78)))

str(dlist)
List of 8
 $ a:List of 1
  ..$ a1:List of 2
  .. ..$ k: num 25
  .. ..$ m: num 34
 $ b:List of 1
  ..$ b1:List of 2
  .. ..$ k: num 23
  .. ..$ m: num 58
 $ c:List of 1
  ..$ c1:List of 2
  .. ..$ k: logi NA
  .. ..$ m: num 32
 $ a:List of 1
  ..$ a2:List of 2
  .. ..$ k: num 42
  .. ..$ m: num 35
 $ c:List of 1
  ..$ c2:List of 2
  .. ..$ k: num 41
  .. ..$ m: num 87
 $ d:List of 1
  ..$ d1:List of 2
  .. ..$ k: num 48
  .. ..$ m: num 90
 $ b:List of 1
  ..$ b2:List of 2
  .. ..$ k: num 85
  .. ..$ m: num 98
 $ b:List of 1
  ..$ b3:List of 2
  .. ..$ k: num 47
  .. ..$ m: num 78

我想组合同名的元素。 combine elements of list of lists with the same name 中有解决方案。但是这里没有保留嵌套组件的名称。

dlist2 <- tapply(unlist(dlist, use.names = F, recursive = F),
                 names(dlist), c)

str(dlist2)
List of 4
 $ a:List of 2
  ..$ :List of 2
  .. ..$ k: num 25
  .. ..$ m: num 34
  ..$ :List of 2
  .. ..$ k: num 42
  .. ..$ m: num 35
 $ b:List of 3
  ..$ :List of 2
  .. ..$ k: num 23
  .. ..$ m: num 58
  ..$ :List of 2
  .. ..$ k: num 85
  .. ..$ m: num 98
  ..$ :List of 2
  .. ..$ k: num 47
  .. ..$ m: num 78
 $ c:List of 2
  ..$ :List of 2
  .. ..$ k: logi NA
  .. ..$ m: num 32
  ..$ :List of 2
  .. ..$ k: num 41
  .. ..$ m: num 87
 $ d:List of 1
  ..$ :List of 2
  .. ..$ k: num 48
  .. ..$ m: num 90
 - attr(*, "dim")= int 4
 - attr(*, "dimnames")=List of 1
  ..$ : chr [1:4] "a" "b" "c" "d"

我正在使用以下代码来保留列表的嵌套组件的名称。

dlist3 <- tapply(unlist(dlist, use.names = T, recursive = F),
                 names(dlist), c)
dlist3 <- lapply(dlist3,
                 function(x) {names(x) <- gsub("^(.+)(\\.)",
                                               "", names(x));  return(x)})
str(dlist3)
List of 4
 $ a:List of 2
  ..$ a1:List of 2
  .. ..$ k: num 25
  .. ..$ m: num 34
  ..$ a2:List of 2
  .. ..$ k: num 42
  .. ..$ m: num 35
 $ b:List of 3
  ..$ b1:List of 2
  .. ..$ k: num 23
  .. ..$ m: num 58
  ..$ b2:List of 2
  .. ..$ k: num 85
  .. ..$ m: num 98
  ..$ b3:List of 2
  .. ..$ k: num 47
  .. ..$ m: num 78
 $ c:List of 2
  ..$ c1:List of 2
  .. ..$ k: logi NA
  .. ..$ m: num 32
  ..$ c2:List of 2
  .. ..$ k: num 41
  .. ..$ m: num 87
 $ d:List of 1
  ..$ d1:List of 2
  .. ..$ k: num 48
  .. ..$ m: num 90

有没有更优雅的方法来做到这一点?

【问题讨论】:

  • 使用purrr 和tibble,您可以执行map_dfr(dlist, ~ enframe(.), .id = "ID") 之类的操作。它与您想要的输出不完全匹配,但它是一个非常方便的结构。

标签: r list nested


【解决方案1】:

您可以使用setNames 和paste0 的名称aveing sequences。使用tapply中的I函数。

res <- with(dlist, tapply(
  setNames(unlist(dlist, recursive=F), 
           paste0(names(dlist), ave(names(dlist), names(dlist), FUN=seq))),
  names(dlist), FUN=I))
str(res)
# List of 4
#  $ a:List of 2
#   ..$ a1:List of 2
#   .. ..$ k: num 25
#   .. ..$ m: num 34
#   ..$ a2:List of 2
#   .. ..$ k: num 42
#   .. ..$ m: num 35
#   ..- attr(*, "class")= chr "AsIs"
#  $ b:List of 3
#   ..$ b1:List of 2
#   .. ..$ k: num 23
#   .. ..$ m: num 58
#   ..$ b2:List of 2
#   .. ..$ k: num 85
#   .. ..$ m: num 98
#   ..$ b3:List of 2
#   .. ..$ k: num 47
#   .. ..$ m: num 78
#   ..- attr(*, "class")= chr "AsIs"
#  $ c:List of 2
#   ..$ c1:List of 2
#   .. ..$ k: logi NA
#   .. ..$ m: num 32
#   ..$ c2:List of 2
#   .. ..$ k: num 41
#   .. ..$ m: num 87
#   ..- attr(*, "class")= chr "AsIs"
#  $ d:List of 1
#   ..$ d1:List of 2
#   .. ..$ k: num 48
#   .. ..$ m: num 90
#   ..- attr(*, "class")= chr "AsIs"
#  - attr(*, "dim")= int 4
#  - attr(*, "dimnames")=List of 1
#   ..$ : chr [1:4] "a" "b" "c" "d"

【讨论】:

    【解决方案2】:

    对调整后的名称使用拆分:

    want <- unlist(dlist, recursive = FALSE)
    names(want) <- gsub("^\\D+\\.", "", names(want))
    want <- split(want, names(dlist))
    str(want)
    
    # List of 4
    # $ a:List of 2
    # ..$ a1:List of 2
    # .. ..$ k: num 25
    # .. ..$ m: num 34
    # ..$ a2:List of 2
    # .. ..$ k: num 42
    # .. ..$ m: num 35
    # $ b:List of 3
    # ..$ b1:List of 2
    # .. ..$ k: num 23
    # .. ..$ m: num 58
    # ..$ b2:List of 2
    # .. ..$ k: num 85
    # .. ..$ m: num 98
    # ..$ b3:List of 2
    # .. ..$ k: num 47
    # .. ..$ m: num 78
    # $ c:List of 2
    # ..$ c1:List of 2
    # .. ..$ k: logi NA
    # .. ..$ m: num 32
    # ..$ c2:List of 2
    # .. ..$ k: num 41
    # .. ..$ m: num 87
    # $ d:List of 1
    # ..$ d1:List of 2
    # .. ..$ k: num 48
    # .. ..$ m: num 90
    

    【讨论】:

      【解决方案3】:

      使用Map、Reduce和append函数,您可以解决问题如下:

      dlist3 <- Map(function(x) Reduce(append, dlist[names(dlist)==x]), unique(names(dlist))) 
      
      str(dlist3)
      #     List of 4
      #     $ a:List of 2
      #     ..$ a1:List of 2
      #     .. ..$ k: num 25
      #     .. ..$ m: num 34
      #     ..$ a2:List of 2
      #     .. ..$ k: num 42
      #     .. ..$ m: num 35
      #     $ b:List of 3
      #     ..$ b1:List of 2
      #     .. ..$ k: num 23
      #     .. ..$ m: num 58
      #     ..$ b2:List of 2
      #     .. ..$ k: num 85
      #     .. ..$ m: num 98
      #     ..$ b3:List of 2
      #     .. ..$ k: num 47
      #     .. ..$ m: num 78
      #     $ c:List of 2
      #     ..$ c1:List of 2
      #     .. ..$ k: logi NA
      #     .. ..$ m: num 32
      #     ..$ c2:List of 2
      #     .. ..$ k: num 41
      #     .. ..$ m: num 87
      #     $ d:List of 1
      #     ..$ d1:List of 2
      #     .. ..$ k: num 48
      #     .. ..$ m: num 90
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-17
        • 2023-02-23
        • 2020-06-25
        • 2011-12-17
        相关资源
        最近更新 更多