[英]Get column names and dataframe name from a list of dataframes into a single dataframe
I am looking for a way to make column names and dataframe names from a list of dataframes into a single dataframe.我正在寻找一种方法来将数据框列表中的列名和数据框名称转换为单个数据框。 They have unequal length of columns.
它们的列长度不等。 What's the best way to do this?
做到这一点的最佳方法是什么?
dlist <- list(mtcars[1:2], mtcars[1:3], mtcars[1:4])
names(dlist) <- c("mtcars1", "mtcars2", "mtcars3")
Tried:
dlist |> map(~colnames(.x))
Expected output:预期输出:
1 mtcars1 mpg cyl NA NA
2 mtcars2 mpg cyl disp NA
3 mtcars3 mpg cyl disp hp
You can try:你可以试试:
library(tidyverse)
dlist %>%
map_df(~names(.x) %>%
enframe(), .id = "id") %>%
pivot_wider(names_from = name, id_cols = id)
# A tibble: 3 x 5
id `1` `2` `3` `4`
<chr> <chr> <chr> <chr> <chr>
1 mtcars1 mpg cyl NA NA
2 mtcars2 mpg cyl disp NA
3 mtcars3 mpg cyl disp hp
Or same idea in base:或在基地相同的想法:
reshape(stack(lapply(dlist, names)), idvar = "ind", timevar = "values", direction = "wide", v.names = "values")
ind values.mpg values.cyl values.disp values.hp
1 mtcars1 mpg cyl <NA> <NA>
3 mtcars2 mpg cyl disp <NA>
6 mtcars3 mpg cyl disp hp
Similar to the accepted solution but more compact thanks to unnest_wider
:类似于公认的解决方案,但由于
unnest_wider
更紧凑:
library(tidyr)
library(tibble)
library(purrr)
dlist %>%
map(colnames) %>%
enframe %>%
unnest_wider(value, names_sep = "_")
#> # A tibble: 3 x 5
#> name value_1 value_2 value_3 value_4
#> <chr> <chr> <chr> <chr> <chr>
#> 1 mtcars1 mpg cyl NA NA
#> 2 mtcars2 mpg cyl disp NA
#> 3 mtcars3 mpg cyl disp hp
Maybe there is a better way but this is how I would do it:也许有更好的方法,但我会这样做:
library(purrr)
dlist %>%
map(~ .x %>%
names() %>%
append(rep(NA_character_, dlist %>%
map(~ .x %>% names()) %>%
reduce(~ max(length(..1), length(..2))) - length(.x)))) %>%
exec(rbind, !!!.) %>%
as.data.frame()
V1 V2 V3 V4
mtcars1 mpg cyl <NA> <NA>
mtcars2 mpg cyl disp <NA>
mtcars3 mpg cyl disp hp
Or a bit more concise with map2
, similar to may dear friend's elegant solution:或者用
map2
更简洁一点,类似于可能亲爱的朋友的优雅解决方案:
dlist %>%
map2_dfr(names(dlist), ~ c(.y, names(.x)) %>% set_names(~ letters[seq_along(.x)])) %>%
column_to_rownames("a")
b c d e
mtcars1 mpg cyl <NA> <NA>
mtcars2 mpg cyl disp <NA>
mtcars3 mpg cyl disp hp
A base R solution is:基本的 R 解决方案是:
dlist |> lapply(names) |>
(\(x){
res <- t(sapply(x, `length<-`, max(lengths(x))))
cbind(id = names(x), setNames(data.frame(res), 1:NCOL(res)))
})()
#R> id 1 2 3 4
#R> mtcars1 mtcars1 mpg cyl <NA> <NA>
#R> mtcars2 mtcars2 mpg cyl disp <NA>
#R> mtcars3 mtcars3 mpg cyl disp hp
Since the row names and id
are the same, then this might do:由于行名和
id
是相同的,那么这可能会:
dlist |> lapply(names) |>
(\(x) sapply(x, `length<-`, max(lengths(x))))() |>
t() |> as.data.frame()
#R> V1 V2 V3 V4
#R> mtcars1 mpg cyl <NA> <NA>
#R> mtcars2 mpg cyl disp <NA>
#R> mtcars3 mpg cyl disp hp
or this one?还是这个?
library(tidyverse)
dlist <- list(mtcars[1:2], mtcars[1:3], mtcars[1:4])
names(dlist) <- c("mtcars1", "mtcars2", "mtcars3")
map_dfr(dlist, ~names(.x) %>% set_names(paste0('col', seq_along(.x))))
#> # A tibble: 3 x 4
#> col1 col2 col3 col4
#> <chr> <chr> <chr> <chr>
#> 1 mpg cyl <NA> <NA>
#> 2 mpg cyl disp <NA>
#> 3 mpg cyl disp hp
If you also want rownames back如果您还想要返回行名
imap_dfr(dlist, ~c(.y, names(.x)) %>% set_names('cc',paste0('col', seq_along(.x)))) %>%
column_to_rownames('cc')
#> col1 col2 col3 col4
#> mtcars1 mpg cyl <NA> <NA>
#> mtcars2 mpg cyl disp <NA>
#> mtcars3 mpg cyl disp hp
Created on 2021-07-02 by the reprex package (v2.0.0)由reprex 包( v2.0.0 ) 于 2021 年 7 月 2 日创建
Another way would be:另一种方法是:
do.call('rbind',
lapply(seq_len(length(dlist)),
function(i) c(names(dlist)[i],
names(dlist[[i]]),
rep(NA, max(sapply(dlist, length)) - ncol(dlist[[i]]))
)
)
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.