Extrahieren Sie Spaltennamen aus einer verschachtelten Liste von data.frames

10

Ich habe eine verschachtelte Liste von data.frames. Was ist der einfachste Weg, um die Spaltennamen aller data.frames abzurufen?

Beispiel:

d = data.frame(a = 1:3, b = 1:3, c = 1:3)

l = list(a = d, list(b = d, c = d))

Ergebnis:

$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c
[1] "a" "b" "c"
user680111
quelle

Antworten:

7

Es gibt bereits einige Antworten. Aber lassen Sie mich einen anderen Ansatz verlassen. Ich habe rapply2()im rawr-Paket verwendet.

devtools::install_github('raredd/rawr')
library(rawr)
library(purrr)

rapply2(l = l, FUN = colnames) %>% 
flatten

$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c
[1] "a" "b" "c"
Jazzurro
quelle
5

Hier ist eine Basis-R-Lösung.

Sie können eine benutzerdefinierte Funktion definieren, um Ihre verschachtelte Liste zu reduzieren (die verschachtelte Listen beliebiger Tiefen , z. B. mehr als 2 Ebenen, verarbeiten kann), d. H.

flatten <- function(x){  
  islist <- sapply(x, class) %in% "list"
  r <- c(x[!islist], unlist(x[islist],recursive = F))
  if(!sum(islist))return(r)
  flatten(r)
}

Verwenden Sie dann den folgenden Code, um die Spaltennamen zu erhalten

out <- Map(colnames,flatten(l))

so dass

> out
$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c
[1] "a" "b" "c"

Beispiel mit einer tieferen verschachtelten Liste

l <- list(a = d, list(b = d, list(c = list(e = list(f= list(g = d))))))
> l
$a
  a b c
1 1 1 1
2 2 2 2
3 3 3 3

[[2]]
[[2]]$b
  a b c
1 1 1 1
2 2 2 2
3 3 3 3

[[2]][[2]]
[[2]][[2]]$c
[[2]][[2]]$c$e
[[2]][[2]]$c$e$f
[[2]][[2]]$c$e$f$g
  a b c
1 1 1 1
2 2 2 2
3 3 3 3

und du wirst bekommen

> out
$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c.e.f.g
[1] "a" "b" "c"
ThomasIsCoding
quelle
4

Hier ist ein Versuch, dies so vektorisiert wie möglich zu tun.

i1 <- names(unlist(l, TRUE, TRUE))
#[1] "a.a1" "a.a2" "a.a3" "a.b1" "a.b2" "a.b3" "a.c1" "a.c2" "a.c3" "b.a1" "b.a2" "b.a3" "b.b1" "b.b2" "b.b3" "b.c1" "b.c2" "b.c3" "c.a1" "c.a2" "c.a3" "c.b1" "c.b2" "c.b3" "c.c1" "c.c2" "c.c3"
i2 <- names(split(i1, gsub('\\d+', '', i1)))
#[1] "a.a" "a.b" "a.c" "b.a" "b.b" "b.c" "c.a" "c.b" "c.c"

Wir können jetzt i2alles vor dem Punkt aufteilen , der geben wird,

split(i2, sub('\\..*', '', i2))

#    $a
#    [1] "a.a" "a.b" "a.c"

#    $b
#    [1] "b.a" "b.b" "b.c"

#    $c
#    [1] "c.a" "c.b" "c.c"

Um sie vollständig zu reinigen, müssen wir eine Schleife ausführen und einen einfachen regulären Ausdruck anwenden.

 lapply(split(i2, sub('\\..*', '', i2)), function(i)sub('.*\\.', '', i))

was gibt,

$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c
[1] "a" "b" "c"

Der Code wurde komprimiert

i1 <- names(unlist(l, TRUE, TRUE))
i2 <- names(split(i1, gsub('\\d+', '', i1)))
final_res <- lapply(split(i2, sub('\\..*', '', i2)), function(i)sub('.*\\.', '', i))
Sotos
quelle
3

Versuche dies

d = data.frame(a = 1:3, b = 1:3, c = 1:3)

l = list(a = d, list(b = d, c = d))

foo <- function(x, f){
    if (is.data.frame(x)) return(f(x))
    lapply(x, foo, f = f)
}

foo(l, names)

Der springende Punkt hier ist, dass es sich data.framestatsächlich um eine spezielle Liste handelt. Daher ist es wichtig, worauf zu testen ist.

Kleine Erklärung: Was hier getan werden muss, ist eine Rekursion, da Sie bei jedem Element entweder einen Datenrahmen betrachten können. Sie möchten also entscheiden, ob Sie namesdie Rekursion anwenden oder tiefer in die Rekursion einsteigen und fooerneut aufrufen .

Georgery
quelle
Das Problem ist, dass foo (l, names) auch eine verschachtelte Liste
zurückgibt
Ich nicht. Ich bin mir nicht sicher, was du anders gemacht hast.
Georgery
Sie können unlist()am Ende hinzufügen , aber ich bin nicht sicher, ob dies das ist, was Sie wollen.
Georgery
2

Erstellen Sie zuerst l1, eine verschachtelte Liste mit nur den Spaltennamen

l1 <- lapply(l, function(x) if(is.data.frame(x)){
  list(colnames(x)) #necessary to list it for the unlist() step afterwards
}else{
  lapply(x, colnames)
})

Dann liste l1 auf

unlist(l1, recursive=F)
Solarion
quelle
2

Hier ist eine Möglichkeit, purrrFunktionen map_depthund zu verwendenvec_depth

library(purrr)

return_names <- function(x) {
   if(inherits(x, "list"))
     return(map_depth(x, vec_depth(x) - 2, names))
    else return(names(x))
}

map(l, return_names)

#$a
#[1] "a" "b" "c"

#[[2]]
#[[2]]$b
#[1] "a" "b" "c"

#[[2]]$c
#[1] "a" "b" "c"
Ronak Shah
quelle