Trích xuất các tên từ một danh sách lồng nhau của data.frames


10

Tôi có một danh sách lồng nhau của data.frames, cách dễ nhất để lấy tên cột của tất cả data.frames là gì?

Thí dụ:

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

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

Kết quả:

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

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

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

Câu trả lời:


7

Đã có một vài câu trả lời. Nhưng hãy để tôi để lại một cách tiếp cận khác. Tôi đã sử dụng rapply2()trong gói rawr.

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"

5

Đây là một giải pháp cơ sở R.

Bạn có thể xác định một chức năng tùy chỉnh để làm phẳng danh sách lồng nhau của mình (có thể xử lý danh sách lồng nhau của bất kỳ độ sâu nào , ví dụ: hơn 2 cấp độ), nghĩa là

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)
}

và sau đó sử dụng mã sau đây để đạt được các tên

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

như vậy mà

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

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

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

Ví dụ với danh sách lồng nhau sâu hơn

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

và bạn sẽ nhận được

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

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

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

4

Đây là một nỗ lực để làm điều này như Vectorized càng tốt,

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"

Bây giờ chúng ta có thể phân chia i2mọi thứ trước dấu chấm, sẽ cho,

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"

Để làm sạch chúng hoàn toàn, chúng ta cần lặp lại và áp dụng một regex đơn giản,

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

cái nào cho

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

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

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

Mã được nén

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

3

Thử cái này

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)

Mấu chốt ở đây là data.framesthực sự là một danh sách đặc biệt, vì vậy điều quan trọng là phải kiểm tra cái gì.

Giải thích nhỏ: những gì cần được thực hiện ở đây là một đệ quy, vì với mọi yếu tố bạn có thể nhìn vào một khung dữ liệu, vì vậy bạn muốn quyết định xem bạn có áp dụng nameshoặc đi sâu hơn vào đệ quy và gọi foolại không.


Vấn đề là foo (l, tên) cũng trả về một danh sách lồng nhau
user680111

Tôi không. Không chắc chắn, những gì bạn đã làm khác nhau.
Georgery

Bạn có thể thêm unlist()vào cuối, nhưng tôi không chắc đây có phải là thứ bạn muốn không.
Georgery

2

Đầu tiên tạo l1, một danh sách lồng nhau chỉ với các tên màu

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)
})

Sau đó hủy niêm yết l1

unlist(l1, recursive=F)

2

Đây là một cách sử dụng các purrrchức năng map_depthvec_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"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.