Ich habe eine unordentliche, stark verschachtelte Liste:

m <- list('form' = list('elements' = list('name' = 'Bob', 'code' = 12), 'name' = 'Mary', 'code' = 15))
> m
$form
$form$elements
$form$elements$name
[1] "Bob"

$form$elements$code
[1] 12


$form$name
[1] "Mary"

$form$code
[1] 15

Wie kann ich aus dem Objekt m die name und code extrahieren, unabhängig davon, wie verschachtelt name und code in einer Liste angezeigt werden?

Erwartete Ausgabe:

# A tibble: 2 x 2
  name   code
  <chr> <dbl>
1 Bob      12
2 Mary     15
r
2
Simon 18 Aug. 2020 im 18:59

2 Antworten

Beste Antwort

1) erneut anwenden m mit rrapply reduzieren, r angeben und dann die Namens- und Codefelder von unlist(r) mit tapply trennen, entfernen Konvertieren Sie die Dimensionen mit c in data.frame und legen Sie die Reihenfolge der Spalten fest.

Beachten Sie, dass dies nicht fest in Name und Code codiert ist und mit anderen Feldern und Feldnummern funktioniert.

library(rrapply)

r <- rrapply(m, f = c, how = "flatten")
nms <- names(r)
as.data.frame(c(tapply(unname(r), nms, unlist)))[unique(nms)]

Geben:

  name code
1  Bob   12
2 Mary   15

Eine Alternative zu den letzten beiden obigen Codezeilen wäre:

out <- unstack(stack(r))
out[] <- lapply(out, type.convert)

Wenn es neben name und code neben name und code noch andere Felder geben könnte, die ignoriert werden sollen, verwenden Sie diese anstelle der Anweisung, die r oben definiert:

cond <- function(x, .xname) .xname %in% c("name", "code")
r <- rrapply(m, cond, c, how = "flatten")

2) Basis R Eine Basis R-Lösung ist die folgende, die die Auflistung von m aufhebt und dann tapply wie in (1) Gruppierung nach den Suffixen von names(r) verwendet. Wie (1) ist dies ein allgemeiner Ansatz, der nicht fest auf name und code codiert ist. Beachten Sie, dass Werkzeuge mit R geliefert werden und somit Teil von Base R sind.

r <- unlist(m)
nms <- tools::file.ext(names(r))
as.data.frame(c(tapply(unname(r), nms, unlist)))[unique(nms)]
5
G. Grothendieck 18 Aug. 2020 im 20:02

Dies könnte helfen, die Liste in einen Datenrahmen zu formatieren und dann neu zu formen:

library(tidyverse)
#Process
y1 <- as.data.frame(lapply(m,unlist),stringsAsFactors = F)
y1$id <- rownames(y1)
rownames(y1)<-NULL
#Dplyr mutation
y1 %>% mutate(Var=ifelse(grepl('name',id,),'name',
                         ifelse(grepl('code',id),'code',NA))) %>%
  select(-id) %>% group_by(Var) %>%
  mutate(i=1:n())%>% pivot_wider(names_from = Var,values_from = form) %>%
  select(-i) %>% mutate(code=as.numeric(code))

Ausgabe:

# A tibble: 2 x 2
  name   code
  <chr> <dbl>
1 Bob      12
2 Mary     15
1
Duck 18 Aug. 2020 im 16:30