R:从未命名的向量列表生成数据帧,其中名称列来自向量名称
R: Generate dataframe from unnamed list of vectors with name-columns from vector names
编辑:很明显,整个场景只是为了妥善解决而纠缠在一起,真正的问题在于创建一堆对象但没有命名它们的代码段。对于给您带来的不便,我深表歉意,我把所有事情都留了下来,以防有人在某个时候遇到同样的问题。
假设我有一个向量列表,例如
a<-c(1); b<-1:3; c<-1:1000
L <- list(a, b, c)
我想将所有这些向量合并到一个数据框中,并添加一列,其中包含值源自的向量的名称。一种方法是
> tibble(x=c(a, b, c), name=rep(c("a", "b", "c"), times=c(1, 3, 1000)))
# A tibble: 1,004 x 2
x name
<dbl> <chr>
1 1 a
2 1 b
3 2 b
4 3 b
5 1 c
6 2 c
7 3 c
8 4 c
9 5 c
10 6 c
# ... with 994 more rows
但是,我有三个以上的向量,并且希望比每次更改一个向量时都必须手动将向量名称放入字符串中更灵活。此外,列表未以开头命名。
我怎样才能将其放入接受任何向量列表和 returns 请求的数据帧的函数中?任何方法 - 无论是从对象列表生成字符串列表,仅从对象创建正确命名的列表,还是直接使用 purrr::map()
或某种形式的 apply()
,都是受欢迎的。
注意:我对 map()
方法的意思是,例如
map_dfr(list(a, b, c), ~tibble("x"=x, "name"={{ x }}))
并且可能会使用某种准引用。这个例子当然没有按预期工作。
回答
给定多个变量,利用 sys.call
:
fun <- function(...) {
n <- sapply(sys.call()[-1], as.character)
L <- list(...)
names(L) <- n
ldply(names(L), function(x) data.frame(x = L[[x]], name = x))
}
str(fun(a, b, c))
输出:
'data.frame': 1004 obs. of 2 variables:
$ x : num 1 1 2 3 1 2 3 4 5 6 ...
$ name: Factor w/ 3 levels "a","b","c": 1 2 2 2 3 3 3 3 3 3 ...
如果没有姓名列表,您可以在创建列表之前创建一个这样的对象
rm(list = ls())
a<-c(1); b<-1:3; c<-1:10
nm <- ls()
my.list <- list(a, b, c)
library(tidyverse)
map2_dfr(my.list, nm, ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
#> x name
#> 1 1 a
#> 2 1 b
#> 3 2 b
#> 4 3 b
#> 5 1 c
#> 6 2 c
#> 7 3 c
#> 8 4 c
#> 9 5 c
#> 10 6 c
#> 11 7 c
#> 12 8 c
#> 13 9 c
#> 14 10 c
由 reprex package (v2.0.0)
于 2021-05-13 创建
对于未命名的列表
a<-c(1); b<-1:3; c<-1:10
my.list <- list(a, b, c)
library(tidyverse)
map2_dfr(my.list, c('a', 'b', 'c'), ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
#> x name
#> 1 1 a
#> 2 1 b
#> 3 2 b
#> 4 3 b
#> 5 1 c
#> 6 2 c
#> 7 3 c
#> 8 4 c
#> 9 5 c
#> 10 6 c
#> 11 7 c
#> 12 8 c
#> 13 9 c
#> 14 10 c
对于命名列表
a<-c(1); b<-1:3; c<-1:20
my.list <- list(a = a, b = b, c= c)
library(tidyverse)
imap_dfr(my.list, ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
#> x name
#> 1 1 a
#> 2 1 b
#> 3 2 b
#> 4 3 b
#> 5 1 c
#> 6 2 c
#> 7 3 c
#> 8 4 c
#> 9 5 c
#> 10 6 c
#> 11 7 c
#> 12 8 c
#> 13 9 c
#> 14 10 c
#> 15 11 c
#> 16 12 c
#> 17 13 c
#> 18 14 c
#> 19 15 c
#> 20 16 c
#> 21 17 c
#> 22 18 c
#> 23 19 c
#> 24 20 c
由 reprex package (v2.0.0)
于 2021-05-13 创建
或
a<-c(1); b<-1:3; c<-1:10
my.list <- list(a, b, c)
names(my.list)
library(tidyverse)
map2_dfr(my.list, names(my.list), ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
编辑:很明显,整个场景只是为了妥善解决而纠缠在一起,真正的问题在于创建一堆对象但没有命名它们的代码段。对于给您带来的不便,我深表歉意,我把所有事情都留了下来,以防有人在某个时候遇到同样的问题。
假设我有一个向量列表,例如
a<-c(1); b<-1:3; c<-1:1000
L <- list(a, b, c)
我想将所有这些向量合并到一个数据框中,并添加一列,其中包含值源自的向量的名称。一种方法是
> tibble(x=c(a, b, c), name=rep(c("a", "b", "c"), times=c(1, 3, 1000)))
# A tibble: 1,004 x 2
x name
<dbl> <chr>
1 1 a
2 1 b
3 2 b
4 3 b
5 1 c
6 2 c
7 3 c
8 4 c
9 5 c
10 6 c
# ... with 994 more rows
但是,我有三个以上的向量,并且希望比每次更改一个向量时都必须手动将向量名称放入字符串中更灵活。此外,列表未以开头命名。
我怎样才能将其放入接受任何向量列表和 returns 请求的数据帧的函数中?任何方法 - 无论是从对象列表生成字符串列表,仅从对象创建正确命名的列表,还是直接使用 purrr::map()
或某种形式的 apply()
,都是受欢迎的。
注意:我对 map()
方法的意思是,例如
map_dfr(list(a, b, c), ~tibble("x"=x, "name"={{ x }}))
并且可能会使用某种准引用。这个例子当然没有按预期工作。
回答
给定多个变量,利用 sys.call
:
fun <- function(...) {
n <- sapply(sys.call()[-1], as.character)
L <- list(...)
names(L) <- n
ldply(names(L), function(x) data.frame(x = L[[x]], name = x))
}
str(fun(a, b, c))
输出:
'data.frame': 1004 obs. of 2 variables:
$ x : num 1 1 2 3 1 2 3 4 5 6 ...
$ name: Factor w/ 3 levels "a","b","c": 1 2 2 2 3 3 3 3 3 3 ...
如果没有姓名列表,您可以在创建列表之前创建一个这样的对象
rm(list = ls())
a<-c(1); b<-1:3; c<-1:10
nm <- ls()
my.list <- list(a, b, c)
library(tidyverse)
map2_dfr(my.list, nm, ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
#> x name
#> 1 1 a
#> 2 1 b
#> 3 2 b
#> 4 3 b
#> 5 1 c
#> 6 2 c
#> 7 3 c
#> 8 4 c
#> 9 5 c
#> 10 6 c
#> 11 7 c
#> 12 8 c
#> 13 9 c
#> 14 10 c
由 reprex package (v2.0.0)
于 2021-05-13 创建对于未命名的列表
a<-c(1); b<-1:3; c<-1:10
my.list <- list(a, b, c)
library(tidyverse)
map2_dfr(my.list, c('a', 'b', 'c'), ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
#> x name
#> 1 1 a
#> 2 1 b
#> 3 2 b
#> 4 3 b
#> 5 1 c
#> 6 2 c
#> 7 3 c
#> 8 4 c
#> 9 5 c
#> 10 6 c
#> 11 7 c
#> 12 8 c
#> 13 9 c
#> 14 10 c
对于命名列表
a<-c(1); b<-1:3; c<-1:20
my.list <- list(a = a, b = b, c= c)
library(tidyverse)
imap_dfr(my.list, ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))
#> x name
#> 1 1 a
#> 2 1 b
#> 3 2 b
#> 4 3 b
#> 5 1 c
#> 6 2 c
#> 7 3 c
#> 8 4 c
#> 9 5 c
#> 10 6 c
#> 11 7 c
#> 12 8 c
#> 13 9 c
#> 14 10 c
#> 15 11 c
#> 16 12 c
#> 17 13 c
#> 18 14 c
#> 19 15 c
#> 20 16 c
#> 21 17 c
#> 22 18 c
#> 23 19 c
#> 24 20 c
由 reprex package (v2.0.0)
于 2021-05-13 创建或
a<-c(1); b<-1:3; c<-1:10
my.list <- list(a, b, c)
names(my.list)
library(tidyverse)
map2_dfr(my.list, names(my.list), ~ .x %>% as.data.frame() %>%
setNames('x') %>% mutate(name = .y))