Сохранение имен вложенных элементов при объединении элементов списка списков с одинаковыми именами - PullRequest
4 голосов
/ 27 марта 2020

У меня есть список списков следующим образом.

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

Я хочу объединить элементы с одинаковыми именами. Есть решение в объединить элементы списка списков с одинаковым именем . Но здесь имена вложенных компонентов не сохраняются.

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

Есть ли более элегантный способ сделать это?

Ответы [ 3 ]

2 голосов
/ 27 марта 2020

Использование разделения с откорректированными именами:

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
2 голосов
/ 27 марта 2020

Используя функции 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
0 голосов
/ 27 марта 2020

Вы можете использовать setNames и paste0 имена, используя ave ing seq uences. Используйте функцию I в tapply.

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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...